datacommsserver/esockserver/ssock/ss_intsock.cpp
changeset 0 dfb7c4ff071f
child 4 928ed51ddc43
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-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 <es_prot.h>
       
    19 #include <comms-infras/ss_roles.h>
       
    20 #include <comms-infras/ss_log.h>
       
    21 #include "es_mbufif.h"
       
    22 #include <ss_glob.h>
       
    23 #include <ss_protprov.h>
       
    24 #include <comms-infras/ss_sapshim.h>
       
    25 #include <comms-infras/ss_intsock.h>
       
    26 #include <in_sock.h>
       
    27 #include "ss_flowrequest.h"
       
    28 #include "ss_sapfactshim.h"
       
    29 #include <comms-infras/ss_nodemessages_dataclient.h>
       
    30 #include <comms-infras/cfmacro.h>
       
    31 #include <comms-infras/ss_msgintercept.h>
       
    32 
       
    33 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    34 #include <es_sock_internal.h>
       
    35 #endif
       
    36 
       
    37 #ifdef SYMBIAN_NETWORKING_UPS
       
    38 #include <comms-infras/ss_platsec_apiext.h>		// MPlatSecApiExt
       
    39 #endif //SYMBIAN_NETWORKING_UPS
       
    40 
       
    41 #ifdef _DEBUG
       
    42 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    43 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    44 _LIT(KSpecAssert_ESockSSocksntsck, "ESockSSocksntsck");
       
    45 #endif
       
    46 
       
    47 
       
    48 using namespace ESock;
       
    49 using namespace Messages;
       
    50 using namespace Factories;
       
    51 using namespace Den;
       
    52 
       
    53 /**
       
    54  @internalComponent
       
    55  */
       
    56 const TUint KAllSelectFlags = (KSockSelectRead | KSockSelectWrite | KSockSelectExcept);
       
    57 
       
    58 #define MSG_PRM(prmIndex)		(prmIndex)
       
    59 
       
    60 
       
    61 ASocket::ASocket(TInt aSocketType)
       
    62 	: iSocketType(aSocketType),
       
    63 	  iIsFlowRequestPending(EFalse)
       
    64 /**
       
    65  Constructor - set up default options.
       
    66  */
       
    67 	{
       
    68 	}
       
    69 
       
    70 const RNodeInterface* ASocket::ServiceProvider() const
       
    71 	{
       
    72 	return iServiceProvider.IsOpen()? &iServiceProvider : NULL;
       
    73 	}
       
    74 
       
    75 TBool ASocket::GetFlowAndSCPR(Messages::TNodeId& aFlow, Messages::TNodeId& aSCPR) const
       
    76     {
       
    77     if (iFlowBinder)
       
    78         {
       
    79     	aFlow = iFlowBinder->Flow()->Id();
       
    80     	aSCPR = iFlowBinder->Flow()->ControlProvider().RecipientId();
       
    81     	return ETrue;
       
    82         }
       
    83     return EFalse;
       
    84     }
       
    85 
       
    86 void ASocket::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
    87     {
       
    88     (void) aRecipient;
       
    89 	ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aMessage, aRecipient);
       
    90 
       
    91 	if (aMessage.IsMessage<TEBase::TError>())
       
    92     	{
       
    93  		// The first error would be from the flow request, any other error iIsFlowRequestPending must be false anyway
       
    94 		if (FlowRequestPending())
       
    95 			{
       
    96 			TEBase::TError& errorMsg(static_cast<TEBase::TError&>(aMessage));
       
    97 			CompleteFlowRequestMessage(errorMsg.iValue);
       
    98 			SetFlowRequestPending(EFalse);
       
    99 			}
       
   100  		//We are no longer needed and the client has been completed too, tear us down.
       
   101 		InitiateDestruction();
       
   102 		}
       
   103     else if (aMessage.IsMessage<TCFDataClient::TBindTo>())
       
   104 		{
       
   105 		TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage));
       
   106 
       
   107 		TInt err;
       
   108 		if (IsClosing())
       
   109 			{
       
   110 			err = KErrAbort;
       
   111 			}
       
   112 		else
       
   113 			{
       
   114 			TRAP(err,BindToL(bindToMsg));
       
   115 			}
       
   116 
       
   117 		RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete(err).CRef());
       
   118 
       
   119 		CompleteFlowRequestMessage(err);
       
   120 		SetFlowRequestPending(EFalse);
       
   121 
       
   122 		if ( IsClosing () )
       
   123 			InitiateDestruction ();
       
   124 		}
       
   125     else
       
   126         {
       
   127    		__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksntsck, 1));
       
   128     	}
       
   129     }
       
   130 
       
   131 void ASocket::BindToL(const TCFDataClient::TBindTo& aBindTo)
       
   132     {
       
   133     __ASSERT_DEBUG(iSSP==NULL, User::Panic(KSpecAssert_ESockSSocksntsck, 2));
       
   134 
       
   135 #ifdef SYMBIAN_NETWORKING_UPS
       
   136 	LOG(ESockLog::Printf(_L8("CSocket %08x:\tBindToL(%08x)"), this, &aBindTo.iNodeId.Node()) );
       
   137 	LOG(ESockLogExternal::Printf(KCFNodeTag, KESockFlowTag, _L8("CSocket %08x:\tSynchronous call: Sender=%08x, Recipient=%08x, Function=BindToL"), this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) );
       
   138 #endif
       
   139 
       
   140 #if defined(__GCCXML__)
       
   141 	CSubConnectionFlowBase* flow = reinterpret_cast<CSubConnectionFlowBase*>(
       
   142 		reinterpret_cast<Messages::ANode*>(
       
   143 			aBindTo.iNodeId.Ptr()
       
   144 			)
       
   145 		);
       
   146 #else
       
   147 	CSubConnectionFlowBase* flow = mcfnode_cast<CSubConnectionFlowBase>(
       
   148 		reinterpret_cast<Messages::ANode*>(
       
   149 			aBindTo.iNodeId.Ptr()
       
   150 			)
       
   151 		);
       
   152 #endif
       
   153 
       
   154     if (flow==NULL)
       
   155         {
       
   156 	    NM_LOG((KESockServerTag, _L8("CSocket %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL Error flow is null"),
       
   157 				this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) )
       
   158         User::Leave(KErrArgument);
       
   159         }
       
   160 
       
   161     NM_LOG((KESockServerTag, _L8("CSocket %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"),
       
   162 			this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) )
       
   163 
       
   164 	// Perform the binding to the flow below
       
   165 	iFlowBinder = flow->GetBinderControlL();
       
   166 	iServiceProvider.Open(iFlowBinder->Flow()->Id());
       
   167 	iSSP = iFlowBinder->GetControlL(iProtocolInfo->iSockType, *this);
       
   168 	iSSPData = iFlowBinder->BindL(*this);
       
   169 
       
   170 	if(RequiresOwnerInfo())
       
   171 		{
       
   172 		CommunicateOwner();
       
   173 		}
       
   174 
       
   175 	// ask the socket provider to perform security policy checking
       
   176 	TInt ret = SecurityCheck();
       
   177     NM_LOG((KESockServerTag, _L8("CSocket %08x:\tSynchronous call: From=%08x To=%08x Func=SecurityCheck Result Error Code=%d"),
       
   178 			this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node(), ret) )
       
   179 	User::LeaveIfError(ret);
       
   180 	iSSP->Start();
       
   181     }
       
   182 
       
   183 
       
   184 void ASocket::AcceptSetupL(const ASocket& aParentSocket, CSubConnectionFlowBase& aFlow)
       
   185 /**
       
   186 Copy constructor type thing for Accept
       
   187 Takes all the useful info from a parent socket, sets up the supplied SSP and
       
   188 Other default values.
       
   189 */
       
   190 	{
       
   191 	iOptions = aParentSocket.iOptions;
       
   192 	iProtocolInfo = aParentSocket.iProtocolInfo;
       
   193 
       
   194     __ASSERT_DEBUG(iFlowBinder==NULL, User::Panic(KSpecAssert_ESockSSocksntsck, 3));
       
   195 	iFlowBinder = aFlow.GetBinderControlL();
       
   196 	iSSP = iFlowBinder->GetControlL(iProtocolInfo->iSockType, *this);
       
   197 	iSSPData = iFlowBinder->BindL(*this);
       
   198 	iIsBound=ETrue;
       
   199 
       
   200 	iRecBufSize=aParentSocket.iRecBufSize;
       
   201 	iSendBufSize=aParentSocket.iSendBufSize;
       
   202 	}
       
   203 
       
   204 void ASocket::Create(TServerProtocolDesc *aServiceInfo)
       
   205 /**
       
   206 Create for all sockets.
       
   207 */
       
   208 	{
       
   209 	/** We create non connection orinted sockets "Open" and sockets without an ssp "NULL" */
       
   210 	if (!aServiceInfo)
       
   211 		{
       
   212 		SetState(ESStateNull);
       
   213 		UnregisterSelf();	// Null sockets need no cookie (and subsequently trying to deregister from a different Accept()ing Player is problematic and adds no benefit
       
   214 		}
       
   215 	else
       
   216 		{
       
   217 		iProtocolInfo=aServiceInfo;
       
   218 		if (!IsConnectionOriented())
       
   219 			{
       
   220 			SetState(ESStateOpen);
       
   221 			}
       
   222 		}
       
   223 
       
   224 	iOptions=KESocketDefaultOptions;
       
   225 	iIsBound=EFalse;
       
   226 
       
   227 #ifdef ESOCK_GULP
       
   228     // allocate extra memory for experimental gulp implementation
       
   229     iRecBufSize=KSocketDefaultBufferSize * 4;
       
   230 #else
       
   231     iRecBufSize=KSocketDefaultBufferSize;
       
   232 #endif
       
   233 	iSendBufSize=KSocketDefaultBufferSize;
       
   234 	}
       
   235 
       
   236 
       
   237 ASocket::~ASocket()
       
   238 /**
       
   239 Socket destructor. Will ensure that the SSP (and any accept queue) is shutdown before destroying it.
       
   240 Automatically completes all outstanding requests.
       
   241 
       
   242 */
       
   243 	{
       
   244 	iServiceProvider.Close();
       
   245 
       
   246 	delete iDisconnectData;
       
   247 	iDatagramTail.Free();	// we should normally have done this in closing
       
   248 	iSendData.Free();		// we should normally have done this in closing
       
   249 
       
   250 	if (iAcceptQ)
       
   251 		{
       
   252 		while (iAcceptQ->Count())
       
   253 			{
       
   254 			TAcceptQEntry a;
       
   255 			iAcceptQ->Remove(&a);
       
   256 
       
   257 			// the SSPs on an accept queue shouldn't have been Start()ed so we don't need to shut them down.
       
   258 			// a.iSSP->DeleteMeNow();	// destruction no longer synchronous & vertical
       
   259 			CTransportFlowShim* shimFlow = factoryobject_cast<CTransportFlowShim>(a.iSSP);
       
   260 
       
   261 		 	// The SAP is no longer owned by the listener socket.
       
   262 			shimFlow->iListenerControlNotify = NULL;
       
   263 
       
   264 			shimFlow->InitDestroy();
       
   265 			delete a.iConnectData;
       
   266 			}
       
   267 		delete iAcceptQ;
       
   268 		}
       
   269 	delete iNextAcceptQ;
       
   270 	delete iAllocAsync;
       
   271 
       
   272 	delete iCurrentMsg;
       
   273 	delete iReadMsg;
       
   274 	delete iWriteMsg;
       
   275 	delete iBlockedCloseMsg;
       
   276 	delete iBlockedConnectMsg;
       
   277 	delete iBlockedIoctlMsg;
       
   278 	delete iBlockedSetLocalNameMsg;
       
   279 	}
       
   280 
       
   281 void ASocket::InitiateDestruction()
       
   282     {
       
   283     SetClosing();
       
   284 
       
   285     if (iSSP)
       
   286 		{
       
   287 		if ((State()==ESStateOpeningActive || State()==ESStateOpeningPassive
       
   288 			|| State()==ESStateOpen || State()==ESStateConnected
       
   289 ||  State()==ESStateBinding
       
   290 			))
       
   291 		    {
       
   292 		    iSSP->Shutdown(MSessionControl::EImmediate);
       
   293 		    }
       
   294 
       
   295 		__ASSERT_DEBUG(iFlowBinder, User::Panic(KSpecAssert_ESockSSocksntsck, 4));
       
   296 		iFlowBinder->Unbind();
       
   297 		}
       
   298 
       
   299     /*
       
   300 		CSubConnectionFlowBase* flow = iFlowBinder->Flow();
       
   301 		if(!flow->HasControlPlane())
       
   302 			{
       
   303 			CNetworkFlow* netFlow = static_cast<CNetworkFlow*>(flow);
       
   304 			delete netFlow;
       
   305 			iSSP = NULL;
       
   306 			delete this;
       
   307 			}
       
   308 
       
   309 		}
       
   310 	else
       
   311 		{
       
   312 		// Either stillborn with OOM or after Shutdown() has detached
       
   313 		delete this;
       
   314 		}
       
   315      */
       
   316     }
       
   317 
       
   318 void ASocket::ShutdownL(RSocket::TShutdown aType, TBool aDisconnectData)
       
   319 /**
       
   320 Terminate the protocol
       
   321 */
       
   322 	{
       
   323 	if (State()==ESStateShuttingDown)
       
   324 		{
       
   325 		PanicSocketClient(EShutDownTwice);
       
   326 		return;
       
   327 		}
       
   328 
       
   329 	if (!CheckRunningAndSetReturn())
       
   330 		{
       
   331 		return;
       
   332 		}
       
   333 
       
   334 	MSessionControl::TCloseType h=MSessionControl::ENormal;
       
   335 	if (SupportsGracefulClose())
       
   336 		{
       
   337 		switch (aType)
       
   338 			{
       
   339 		case RSocket::ENormal:
       
   340 			CompleteWrite(KErrCancel);
       
   341 			CompleteRead(KErrCancel);
       
   342 			h=MSessionControl::ENormal;
       
   343 			iBlockedOperations|=(EReadStopped|EWriteStopped);
       
   344 			break;
       
   345 		case RSocket::EStopInput:
       
   346 			CompleteRead(KErrCancel);
       
   347 			h=MSessionControl::EStopInput;
       
   348 			iBlockedOperations|=EReadStopped;
       
   349 			iDatagramTail.Free();
       
   350 			break;
       
   351 		case RSocket::EStopOutput:
       
   352 			h=MSessionControl::EStopOutput;
       
   353 			iBlockedOperations|=EWriteStopped;
       
   354 			CompleteWrite(KErrCancel);
       
   355 			break;
       
   356 		case RSocket::EImmediate:
       
   357 			h=MSessionControl::EImmediate;
       
   358 			CompleteWrite(KErrCancel);
       
   359 			CompleteRead(KErrCancel);
       
   360 			iDatagramTail.Free();
       
   361 			break;
       
   362 			}
       
   363 		}
       
   364 	else
       
   365 		{
       
   366 		CompleteWrite(KErrCancel);
       
   367 		CompleteRead(KErrCancel);
       
   368 		h=MSessionControl::EImmediate;
       
   369 		}
       
   370 
       
   371 	CompleteConnect(KErrCancel);
       
   372 	CompleteSetLocalName(KErrCancel);
       
   373 
       
   374 	SetState(ESStateShuttingDown);
       
   375 
       
   376 	if(h!=MSessionControl::EImmediate)
       
   377 	    {
       
   378 	    SetBlockedClose();
       
   379 	    DontCompleteCurrentRequest();
       
   380 	    }
       
   381 
       
   382 	if (CanSendDisconnectData() && h!=MSessionControl::EImmediate && aDisconnectData)
       
   383 		{
       
   384         TDes8& sendBuf = *BorrowTemporaryBufferL(iSendBufSize);
       
   385 		ReadParamL(ESocketCurrentMessage,MSG_PRM(1),sendBuf);
       
   386 		iSSP->Shutdown(h,sendBuf);
       
   387 		}
       
   388 	else
       
   389 		{
       
   390 		iSSP->Shutdown(h);
       
   391 		}
       
   392 
       
   393 	if (iErrorOperationMask & MSessionControlNotify::EErrorClose)
       
   394 		{
       
   395 		SetReturn(iError);
       
   396 		ClearErrorIfNotFatal(); //Sets iError = 0;
       
   397 		iErrorOperationMask = 0;
       
   398 		}
       
   399 	// OK to access socket because a CanClose would set the socket state to dead
       
   400 	else if (h==MSessionControl::EImmediate)
       
   401 		{
       
   402 		// Set state to dead - let close delete the socket
       
   403 		SetState(ESStateDead);
       
   404 		}
       
   405 	else
       
   406 		{
       
   407 		if (!(iOptions & KOptBlocking) && IsBlockedClose())
       
   408 			{
       
   409 			CompleteClose(KErrWouldBlock);
       
   410 			}
       
   411 		}
       
   412 	}
       
   413 
       
   414 TBool ASocket::CloseSocket()
       
   415 /**
       
   416 A Client has closed our RSocket - or we're being closed by the session because our client has exited
       
   417 */
       
   418 	{
       
   419 	SetClosing();
       
   420 	TBool immediateClose = EFalse;
       
   421 	switch (State())
       
   422 		{
       
   423 	case ESStateNull:
       
   424 	case ESStateAccepting:
       
   425 	case ESStateCreated:
       
   426 	case ESStateError:
       
   427 	case ESStateDead:
       
   428 	case ESStateDisconnected:
       
   429 		immediateClose = ETrue;
       
   430 		break;
       
   431 
       
   432 	case ESStateShuttingDown:
       
   433         CompleteClose(KErrCancel);
       
   434 		SetReturn(KErrAlreadyExists);
       
   435 		SetState(ESStateClosing);
       
   436 		immediateClose = ETrue;
       
   437 		break;
       
   438 
       
   439 	case ESStateOpeningActive:
       
   440 	case ESStateOpeningPassive:
       
   441 	case ESStateOpen:
       
   442 	case ESStateConnected:
       
   443 	case ESStateBinding:
       
   444         {
       
   445 		SetState(ESStateClosing);
       
   446 
       
   447         TBool graceful = SupportsGracefulClose() && iSSP;
       
   448 		// CanClose will be called irrespective of whether the socket
       
   449 		// supports graceful close or not.
       
   450 		// ASocket can take care of the ownership of deletion via InitiateDestruction.
       
   451 		// Also, CanClose will call InitiateDestruction if we are in ESStateClosing.
       
   452 		// We already set to ESStateClosing.
       
   453 	    SetBlockedClose();
       
   454 	    DontCompleteCurrentRequest(); // Block closes regardless of NonBlocking mode state
       
   455 
       
   456         if (graceful)
       
   457            	{
       
   458 	        iSSP->Shutdown(MSessionControl::ENormal);
       
   459 	        }
       
   460         else
       
   461            	{
       
   462            	if (iSSP)
       
   463                	{
       
   464                	iSSP->Shutdown(MSessionControl::EImmediate);
       
   465                	}
       
   466             CanClose(MSessionControlNotify::EDelete);
       
   467             }
       
   468         }
       
   469         break;
       
   470 
       
   471 	case ESStateClosing:
       
   472 		PanicSocketClient(ECloseTwice);
       
   473 		break;
       
   474 		}
       
   475 	return immediateClose;
       
   476 	}
       
   477 
       
   478 void ASocket::BindL()
       
   479 /**
       
   480 Set local address from a client request.
       
   481 */
       
   482 	{
       
   483 	if (!CheckRunningAndSetReturn())
       
   484 		{
       
   485 		return;
       
   486 		}
       
   487 
       
   488 	if (IsConnectionOriented() && iIsBound)
       
   489 		{
       
   490 		SetReturn(KErrAlreadyExists);
       
   491 		}
       
   492 	else
       
   493 if (State() == ESStateBinding)
       
   494 		{
       
   495 		SetReturn(KErrInUse);
       
   496 		}
       
   497 		else
       
   498 		{
       
   499 		TSockAddr a;
       
   500 		ReadParamL(ESocketCurrentMessage,MSG_PRM(0),a);
       
   501 		
       
   502 		
       
   503 		// Set to blocked before call to SetLocalName. This allows for immediate callback,
       
   504 		// as some conditions may not require asynchronous processing.
       
   505 		SetBlockedSetLocalName();
       
   506 		DontCompleteCurrentRequest();
       
   507 
       
   508 		// Save off the state for transition later.
       
   509 		iNextState = State();
       
   510 		SetState(ESStateBinding);
       
   511 		
       
   512 		iSSP->SetLocalName(a);
       
   513 
       
   514 		}
       
   515 	}
       
   516 
       
   517 void ASocket::AutoBind()
       
   518 	{
       
   519 	iSSP->AutoBind();
       
   520 	iIsBound=ETrue;
       
   521 	}
       
   522 
       
   523 
       
   524 void ASocket::ConnectL(TBool aConnectData)
       
   525 /**
       
   526 Active open the socket - from a client request.
       
   527 */
       
   528 	{
       
   529 	TSockAddr a;
       
   530 	TInt ret=KErrNone;
       
   531 	switch (State())
       
   532 		{
       
   533 	case ESStateOpeningActive:
       
   534 	case ESStateOpeningPassive:
       
   535 		PanicSocketClient(EConnectingAlready);
       
   536 		break;
       
   537 		
       
   538 		case ESStateBinding:
       
   539 		SetReturn(KErrInUse);
       
   540 		break;
       
   541 
       
   542 	case ESStateConnected:
       
   543 		if (IsConnectionOriented())
       
   544 			{
       
   545 			if(IsBlockedConnect())
       
   546 				{
       
   547 				PanicSocketClient(EConnectingAlready);
       
   548 				}
       
   549 
       
   550 			SetReturn(KErrAlreadyExists);
       
   551 			return;
       
   552 			}
       
   553 		// Fall through - non connection oriented sockets can call Connect as much as they like.
       
   554 	case ESStateOpen:
       
   555 	case ESStateCreated:
       
   556 		{
       
   557 		ReadParamL(ESocketCurrentMessage,MSG_PRM(0),a);
       
   558 
       
   559 		ret=iSSP->SetRemName(a);
       
   560 		if (ret!=KErrNone)
       
   561 			{
       
   562 			SetReturn(ret);
       
   563 			return;
       
   564 			}
       
   565 
       
   566 		if(!iIsBound)
       
   567 			{
       
   568 			SetBlockedConnect();
       
   569 			DontCompleteCurrentRequest();
       
   570 			
       
   571 			if (!IsConnectionOriented())
       
   572 			    {
       
   573 			    iNextState = ESStateConnected;
       
   574 				}
       
   575 			else
       
   576 				{
       
   577 				iConnectData = aConnectData;
       
   578 			    iNextState = ESStateOpeningActive;
       
   579 				}
       
   580 			SetState(ESStateBinding);
       
   581 			AutoBind();
       
   582 
       
   583 			if (!(iOptions&KOptBlocking) && IsBlockedConnect())
       
   584 				{
       
   585 				CompleteConnect(KErrWouldBlock);
       
   586 				}
       
   587 			return;
       
   588 		
       
   589 			}
       
   590 
       
   591 		if (!IsConnectionOriented())
       
   592 		    {
       
   593 			SetState(ESStateConnected);
       
   594 			TryToCompleteSelectIoctl();
       
   595 		    }
       
   596 		else
       
   597 			{
       
   598 
       
   599 			SetBlockedConnect();
       
   600 			DontCompleteCurrentRequest();
       
   601 
       
   602 			SetState(ESStateOpeningActive);
       
   603 			
       
   604 			if (CanSendConnectData() && aConnectData)
       
   605 				{
       
   606 				TDes8& sendBuf = *BorrowTemporaryBufferL(iSendBufSize);
       
   607 				ReadParamL(ESocketCurrentMessage,MSG_PRM(1),sendBuf);
       
   608 				iSSP->ActiveOpen(sendBuf);
       
   609 				}
       
   610 			else
       
   611 				{
       
   612 				iSSP->ActiveOpen();
       
   613 				}
       
   614 
       
   615 			if (!(iOptions&KOptBlocking) && IsBlockedConnect())
       
   616 				{
       
   617 				CompleteConnect(KErrWouldBlock);
       
   618 				}
       
   619 			}
       
   620 		}
       
   621 		break;
       
   622 	case ESStateDisconnected:
       
   623 	case ESStateShuttingDown:
       
   624 	case ESStateClosing:
       
   625 	case ESStateDead:
       
   626 		SetReturn(KErrBadHandle);
       
   627 		break;
       
   628 	case ESStateError:
       
   629 		SetReturn(iError);
       
   630 		return;
       
   631 	default:
       
   632         PanicSocketClient(ECannotConnect);
       
   633 		//Fault(EBadState);
       
   634 		break;
       
   635 		}
       
   636 
       
   637 	}
       
   638 
       
   639 //indexes of the data elements in RMessage for Get/SetOpt
       
   640 #define  OPT_NAME_INDEX		    0
       
   641 #define  OPT_OPTION_INDEX		1 //for the option value
       
   642 #define  OPT_OPT_LENGTH_INDEX	2
       
   643 #define  OPT_OPT_LEVEL_INDEX	3
       
   644 
       
   645 /**
       
   646     Set a socket option from a client request
       
   647 */
       
   648 void ASocket::SetSockOptionL(TInt aOptionName, TInt aOptionLength, TInt aOptionLevel)
       
   649 	{
       
   650 
       
   651 	if (aOptionName & KSocketInternalOptionBit)
       
   652 		{
       
   653 		SetReturn(KErrAccessDenied);
       
   654 		return;
       
   655 		}
       
   656 
       
   657 	if (aOptionLevel==KSOLSocket)
       
   658 		{
       
   659 
       
   660 		TBufC8<sizeof(TUint)> smallOptionBuf;
       
   661   		TPtr8 option=smallOptionBuf.Des();
       
   662 
       
   663 		switch(aOptionName)
       
   664 			{
       
   665 			case KSOSendBuf:
       
   666 				{
       
   667 				ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   668 				iSendBufSize=*(TUint*)smallOptionBuf.Ptr();
       
   669 
       
   670 				// Even though we don't respect the sendbuf size for transfers we need to
       
   671 				// be able to echo the value back to a GetOpt() - also it's used for
       
   672 				// sizing the Connect/Shutdown_WithData operations
       
   673 				if (iSendBufSize==KSocketBufSizeUndefined)
       
   674 					{
       
   675 					iSendBufSize=KSocketDefaultBufferSize;
       
   676 					iOptions&=~KOptSendBufSet;
       
   677 					break;
       
   678 					}
       
   679 
       
   680 				iOptions|=KOptSendBufSet;
       
   681 				break;
       
   682 				}
       
   683 			case KSORecvBuf:
       
   684 				{
       
   685 	            ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   686 				iRecBufSize=*(TUint*)smallOptionBuf.Ptr();
       
   687 
       
   688                 // Even though we don't respect the recvbuf size for transfers we need to
       
   689                 // be able to echo the value back to a GetOpt()
       
   690 				if (iRecBufSize==KSocketBufSizeUndefined)
       
   691 					{
       
   692 					iOptions&=~KOptRecBufSet;
       
   693 					break;
       
   694 					}
       
   695 				iOptions|=KOptRecBufSet;
       
   696 				break;
       
   697 				}
       
   698 
       
   699 			case KSODebug:
       
   700 				{
       
   701 				ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   702 				TBool b;
       
   703 				TPtr8 p((TUint8*)&b,sizeof(iSendBufSize),sizeof(iSendBufSize));
       
   704 				ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),p);
       
   705 				if(*(TBool*)option.Ptr())
       
   706 					{
       
   707 					iOptions|=KOptDebug;
       
   708 					}
       
   709 				else
       
   710 					{
       
   711 					iOptions&=~KOptDebug;
       
   712 					}
       
   713 				break;
       
   714 				}
       
   715 			case KSONonBlockingIO:
       
   716 				iOptions &= ~KOptBlocking;
       
   717 				break;
       
   718 			case KSOBlockingIO:
       
   719 				iOptions |= KOptBlocking;
       
   720 				break;
       
   721 
       
   722 			//-- enable socket transfer to another process with capabilities check.
       
   723 			//-- socket option must be TPckgBuf<TSecurityPolicy>, TSecurityPolicy in turn must contain the capabilities set for the
       
   724 			//-- process that is going to receive this socket as a result of RSocket::Transfer().
       
   725 			case    KSOEnableTransfer:
       
   726 				{
       
   727 				if(State() == ESStateNull || State() == ESStateAccepting)
       
   728 					{
       
   729 					User::Leave(KErrNotReady);
       
   730 					}
       
   731 			    //-- read security information (capabilities set) from the client
       
   732 			    TSecurityPolicyBuf secPolicyBuf;
       
   733 			    ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),secPolicyBuf);
       
   734 
       
   735 			    //-- store the capabilities set for the future check in ProtocolManager::TransferSocketL()
       
   736 			    iSecTransferEnabled=EFalse;
       
   737 			    User::LeaveIfError(iTransferSecPolicy.Set(secPolicyBuf));
       
   738 			    iSecTransferEnabled=ETrue; //-- indication that the RSocket::Transfer() security information is ready to check
       
   739 				}
       
   740 			break;
       
   741 
       
   742 			//-- Disable socket transfer by indicating that the transfer security information is not valid
       
   743 			case    KSODisableTransfer:
       
   744 			    iSecTransferEnabled=EFalse;
       
   745 			break;
       
   746 
       
   747 
       
   748 			default:
       
   749 				SetReturn(KErrNotSupported);
       
   750 			}
       
   751 		}
       
   752 	else
       
   753 		{
       
   754 		if (CheckRunningAndSetReturn())
       
   755 			{
       
   756 			HBufC8* optionBuf=NULL;
       
   757 			optionBuf=HBufC8::NewMaxLC(aOptionLength);
       
   758 			TPtr8 option=optionBuf->Des();
       
   759 			ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   760 			SetReturn(iSSP->SetOption(aOptionLevel,aOptionName,option));
       
   761 			CleanupStack::PopAndDestroy(optionBuf);
       
   762 			}
       
   763 		}
       
   764 	}
       
   765 
       
   766 void ASocket::GetSockOptionL(TInt aOptionName, TInt aOptionLength, TInt aOptionLevel, TInt aWriteBack)
       
   767 /**
       
   768 Read a socket option from us (or attempt the protocol if we don't support the option)
       
   769 
       
   770 */
       
   771 	{
       
   772 
       
   773 	if (aOptionName&KSocketInternalOptionBit)
       
   774 		{
       
   775 		SetReturn(KErrAccessDenied);
       
   776 		return;
       
   777 		}
       
   778 	if (aOptionLevel==KSOLSocket)
       
   779 		{
       
   780 		// Most KSOLSocket options use argument1 as an out parameter
       
   781 		switch(aOptionName)
       
   782 			{
       
   783 		case KSOSendBuf:
       
   784 		case KSORecvBuf:
       
   785 		case KSODebug:
       
   786 		case KSONonBlockingIO:
       
   787 		case KSOBlockingIO:
       
   788 		case KSOSelectPoll:
       
   789 			{
       
   790 			if(aWriteBack)
       
   791 				{
       
   792 				// Retrieve the required value
       
   793 				TUint optionVal;
       
   794 				switch(aOptionName)
       
   795 					{
       
   796 				case KSOSendBuf:
       
   797 					{
       
   798 					optionVal =iSendBufSize;
       
   799 					break;
       
   800 					}
       
   801 				case KSORecvBuf:
       
   802 					{
       
   803 					optionVal =iRecBufSize;
       
   804 					break;
       
   805 					}
       
   806 				case KSODebug:
       
   807 					{
       
   808 					optionVal =(iOptions&KOptDebug);
       
   809 					break;
       
   810 					}
       
   811 				case KSONonBlockingIO:
       
   812 					{
       
   813 					optionVal =!(iOptions&KOptBlocking);
       
   814 					break;
       
   815 					}
       
   816 				case KSOBlockingIO:
       
   817 					{
       
   818 					optionVal =iOptions&KOptBlocking;
       
   819 					break;
       
   820 					}
       
   821 				case KSOSelectPoll:
       
   822 					{
       
   823 					if(CheckRunningAndSetReturn())
       
   824 						{
       
   825 						optionVal =SelectConditionsReady();
       
   826 						}
       
   827 					else
       
   828 						{
       
   829 						aWriteBack = EFalse;
       
   830 						}
       
   831 					break;
       
   832 					}
       
   833                 // coverity [dead_error_begin] :
       
   834 				default:
       
   835 			        // the default should never be called and is there to catch coding errors.
       
   836 					__ASSERT_DEBUG(0, User::Panic(KSpecAssert_ESockSSocksntsck, 5));
       
   837 				}
       
   838 				if(aWriteBack)
       
   839 					{
       
   840 					TPckg <TUint> option(optionVal);
       
   841 					WriteParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   842 					}
       
   843 				}
       
   844 			else
       
   845 				{
       
   846 				// Somehow they passed a NULL second argument - should we panic them?
       
   847 				SetReturn(KErrArgument);
       
   848 				}
       
   849 
       
   850 			break;
       
   851 			}
       
   852 		case KSOSelectLastError:
       
   853 			{
       
   854 			SetReturn(iError);
       
   855 					
       
   856 			if(aWriteBack)
       
   857 				{
       
   858 				TPckg <TUint> option(iError);
       
   859 				WriteParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   860 				}
       
   861 			else
       
   862 				{
       
   863 				// Somehow they passed a NULL second argument - should we panic them?
       
   864 				SetReturn(KErrArgument);
       
   865 				}
       
   866 						
       
   867 		    ClearErrorIfNotFatal();
       
   868 			break;
       
   869 			}
       
   870 
       
   871 		case KSOReadBytesPending:
       
   872 		case KSOUrgentDataOffset:
       
   873 			{
       
   874 			if(!CheckRunningAndSetReturn())
       
   875 				{
       
   876 				break;
       
   877 				}
       
   878 
       
   879 			if(aOptionName==((TInt)KSOUrgentDataOffset) && !CanSendUrgentData())
       
   880 				{
       
   881 				SetReturn(KErrNotSupported);
       
   882 				break;
       
   883 				}
       
   884 			TSockXfrLength len;
       
   885 			len()=iRecOffset;
       
   886 			SetReturn(iSSP->GetOption(aOptionLevel,aOptionName,len));
       
   887 			if (aWriteBack)
       
   888 				{
       
   889 				WriteParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),len);
       
   890 				}
       
   891 			break;
       
   892 			}
       
   893 		default:
       
   894 			SetReturn(KErrNotSupported);
       
   895 		}
       
   896 		}
       
   897 
       
   898 	else
       
   899 		{
       
   900 		if(CheckRunningAndSetReturn())
       
   901 			{
       
   902 			if (aWriteBack)
       
   903 				{
       
   904 				RBuf8 optionBuf;
       
   905 				optionBuf.CreateMaxL(aOptionLength);
       
   906 				CleanupClosePushL(optionBuf);
       
   907 				TPtr8 option=optionBuf.MidTPtr(0);
       
   908 				ReadParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   909 				SetReturn(iSSP->GetOption(aOptionLevel,aOptionName,option));
       
   910 				WriteParamL(ESocketCurrentMessage,MSG_PRM(OPT_OPTION_INDEX),option);
       
   911 				CleanupStack::PopAndDestroy(&optionBuf);
       
   912 				}
       
   913 			else
       
   914         		{
       
   915         		SetReturn(KErrArgument);
       
   916         		}
       
   917 			}
       
   918 		}
       
   919 	}
       
   920 
       
   921 void ASocket::IoctlL(TInt aOptionName, TInt aOptionLength, TInt aOptionLevel, TBool aReadOption)
       
   922 /**
       
   923 Perform an Ioctl from a user request
       
   924 */
       
   925 	{
       
   926 
       
   927 	if (IsBlockedIoctl())
       
   928 		{
       
   929 		PanicSocketClient(ETwoIoctls);
       
   930 		return;
       
   931 		}
       
   932 
       
   933 	if (aOptionName&KInternalIoctlBit)
       
   934 		{
       
   935 		SetReturn(KErrAccessDenied);
       
   936 		return;
       
   937 		}
       
   938 
       
   939 	if (aOptionLevel==KSOLSocket)
       
   940 		{
       
   941 
       
   942 		if(aOptionName==(TInt)KIOctlSelect)
       
   943 		    {
       
   944 
       
   945 			if(!CheckRunningAndSetReturn())
       
   946 				{
       
   947 				return;
       
   948 				}
       
   949             TPckgBuf<TUint> flags;
       
   950 			ReadParamL(ESocketCurrentMessage,MSG_PRM(1), flags);
       
   951 			iSelectFlags=flags();
       
   952 			if((iSelectFlags&KAllSelectFlags)!=0)
       
   953 			    {
       
   954                 SetBlockedIoctl();
       
   955 		        DontCompleteCurrentRequest();
       
   956 			    TryToCompleteSelectIoctl();
       
   957 			    }
       
   958 			else
       
   959 				{
       
   960                 SetReturn(KErrArgument);
       
   961                 }
       
   962 		    }
       
   963 		else
       
   964 			{
       
   965 		    SetReturn(KErrNotSupported);
       
   966 		    }
       
   967 		}
       
   968 	else
       
   969 		{
       
   970 //		if(!(iOptions & KOptBlocking))
       
   971 //			{
       
   972 //			SetReturn(KErrWouldBlock);
       
   973 //			return;
       
   974 //          }
       
   975 
       
   976 //		if (CheckRunningAndSetReturn()==EFalse)
       
   977 //	        return;
       
   978 		if(iSSP == NULL)
       
   979 			{
       
   980 		    SetReturn(KErrNotSupported);
       
   981 			return;
       
   982 			}
       
   983 
       
   984 		if (aReadOption)
       
   985 			{
       
   986 			if(aOptionLength < 0)
       
   987 				{
       
   988 				User::Leave(aOptionLength);
       
   989 				}
       
   990 			HBufC8* ioctlBuf=HBufC8::NewLC(aOptionLength);
       
   991 			TPtr8 des=ioctlBuf->Des();
       
   992 			ReadParamL(ESocketCurrentMessage,MSG_PRM(1),des);
       
   993 			// only set ioctl blocked if successfull allocation
       
   994 			SetBlockedIoctl();
       
   995 			DontCompleteCurrentRequest();
       
   996 
       
   997 			iSSP->Ioctl(aOptionLevel,aOptionName,&des);
       
   998             CleanupStack::PopAndDestroy(ioctlBuf);
       
   999 			}
       
  1000 		else
       
  1001 			{
       
  1002 			SetBlockedIoctl();
       
  1003 			DontCompleteCurrentRequest();
       
  1004 			iSSP->Ioctl(aOptionLevel,aOptionName,NULL);
       
  1005 			}
       
  1006 		}
       
  1007 	LOG(
       
  1008 		if (IsBlockedIoctl())
       
  1009 			{
       
  1010 			ESockLog::Printf(KESockSessDetailTag, _L8("ASocket::IoctlL blocking") );
       
  1011 			}
       
  1012 		)
       
  1013 	}
       
  1014 
       
  1015 void ASocket::CancelIoctl()
       
  1016 /**
       
  1017 Cancel a pending Ioctl and notify the protocol.
       
  1018 */
       
  1019 	{
       
  1020 	if(IsBlockedIoctl())
       
  1021 		{
       
  1022 		TInt optionLevel = 0;
       
  1023 		TInt optionName = 0;
       
  1024 		if(!iSelectFlags)
       
  1025 			{
       
  1026 			optionLevel = iBlockedIoctlMsg->ReadInt(2);
       
  1027 			optionName = iBlockedIoctlMsg->ReadInt(0);
       
  1028 			}
       
  1029 
       
  1030 		CompleteIoctl(KErrCancel);
       
  1031 
       
  1032 		if(iSelectFlags)
       
  1033 			{
       
  1034 		    iSelectFlags=0;
       
  1035 			}
       
  1036 		else
       
  1037 			{
       
  1038 			__ASSERT_ALWAYS(iSSP!=NULL, Panic(ENullSap));
       
  1039 		    iSSP->CancelIoctl(optionLevel, optionName);
       
  1040 			}
       
  1041 		}
       
  1042 	}
       
  1043 
       
  1044 void ASocket::GetDisconnectDataL( ) const
       
  1045 /**
       
  1046 Get disconnect data if any is present on the socket.
       
  1047 */
       
  1048 	{
       
  1049 	if (CanSendDisconnectData())
       
  1050 		{
       
  1051 		if(iDisconnectDataError!=KErrNone)
       
  1052 			{
       
  1053 			SetReturn(iDisconnectDataError);
       
  1054 			}
       
  1055 		else if (iDisconnectData)
       
  1056 			{
       
  1057 			TPtr8 des=iDisconnectData->Des();
       
  1058 			const_cast<ASocket*>(this)->WriteParamL(ESocketCurrentMessage,MSG_PRM(0),des);
       
  1059 			}
       
  1060 		else
       
  1061 			{
       
  1062 			SetReturn(KErrNotFound);
       
  1063 			}
       
  1064 		}
       
  1065 	else
       
  1066 		{
       
  1067 		SetReturn(KErrNotSupported);
       
  1068 		}
       
  1069 	}
       
  1070 
       
  1071 static const TInt KPaddingForHeaders = 48;
       
  1072 
       
  1073 void ASocket::SendL(TInt aXferLenArg, TInt aAddrArg, TInt aSendByteCount, TInt aSendFlags, TBool aUseMBufs)
       
  1074 /**
       
  1075  Common message service for Send, SendTo and Write.
       
  1076 */
       
  1077 	{
       
  1078 	if (IsBlockedWrite())
       
  1079 		{
       
  1080 		PanicSocketClient(EWritingAlready);
       
  1081 		return;
       
  1082 		}
       
  1083 
       
  1084 	if (!CheckRunningAndSetReturn())
       
  1085 		{
       
  1086 		return;
       
  1087 		}
       
  1088 
       
  1089 	// Judge If the socket is connected during a connection-oriented service.
       
  1090 	if (IsConnectionOriented() && iState != ESStateConnected)
       
  1091 		{
       
  1092 		LOG( ESockLog::Printf(_L("ASocket %08x SendL() KErrNotReady"), this ) );
       
  1093 		SetReturn(KErrNotReady);
       
  1094 		return;
       
  1095 		}
       
  1096 
       
  1097 	if(iBlockedOperations & EWriteStopped)
       
  1098 		{
       
  1099 		if(aXferLenArg >= 0)
       
  1100 			{
       
  1101 			iXferLength() = 0;
       
  1102 			WriteParamL(ESocketCurrentMessage, aXferLenArg, iXferLength);
       
  1103 			}
       
  1104 		SetReturn(KErrEof);
       
  1105 		return;
       
  1106 		}
       
  1107 
       
  1108 	// Set whether we are sending RMbufChain or not
       
  1109 	iSendUseMBufs = aUseMBufs;
       
  1110 
       
  1111 	iSendByteCount=aSendByteCount;
       
  1112 	iSendXferLenIdx = aXferLenArg;
       
  1113 	iSendToAddrIdx = aAddrArg;
       
  1114     if (iSendToAddrIdx >= 0)
       
  1115         {
       
  1116         if(IsConnectionOriented())
       
  1117             {
       
  1118             PanicSocketClient(ECantSendToOnConnection);
       
  1119             return;
       
  1120             }
       
  1121         }
       
  1122     else    // Not ESendTo...
       
  1123         {
       
  1124         if(State() != ESStateConnected  && State() != ESStateShuttingDown && iSendToAddrIdx != ASocket::KWriteNoAddrArg)
       
  1125             {
       
  1126             LOG( ESockLog::Printf(_L("ASocket %08x SendL() 2 KErrNotReady"), this ) );
       
  1127             SetReturn(KErrNotReady);
       
  1128             return;
       
  1129             }
       
  1130         }
       
  1131 	iSendFlags = aSendFlags;
       
  1132 	if(iSendFlags)
       
  1133 	    {
       
  1134         if(iSendFlags&KSocketInternalWriteBit)
       
  1135             {
       
  1136             SetReturn(KErrAccessDenied);
       
  1137             return;
       
  1138             }
       
  1139         if ((iSendFlags&KSockWriteUrgent) && !CanSendUrgentData())
       
  1140             {
       
  1141             SetReturn(KErrNotSupported);
       
  1142             return;
       
  1143             }
       
  1144 	    }
       
  1145 	__ASSERT_DEBUG(iSendData.IsEmpty(), Fault(EBufsLeftInSendData));	// no pathway should leave this populated after Write completes
       
  1146 	iSendData.Free();	// but paranoia is cheap 
       
  1147 
       
  1148 	if(iSendByteCount<0)
       
  1149 		{
       
  1150 		PanicSocketClient(EBadDescriptorLength);
       
  1151 		return;
       
  1152 		}
       
  1153 	
       
  1154 #ifdef SYMBIAN_NETWORKING_PERFMETRICS
       
  1155 	IncludePerformanceData(-1, -1, iSendByteCount);
       
  1156 #endif
       
  1157 
       
  1158 	if (iIsBound==EFalse)
       
  1159 		{
       
  1160 
       
  1161 		if (State() == ESStateBinding)
       
  1162 			{
       
  1163 			SetReturn(KErrInUse);
       
  1164 			return;
       
  1165 			}
       
  1166 		AutoBind();
       
  1167 		}
       
  1168 	iSendOffset=0;
       
  1169 	DoSend(ETrue);
       
  1170 	}
       
  1171 
       
  1172 void ASocket::DoSend(TBool aInitialRequest)
       
  1173 	{
       
  1174 	AMessage* msg = aInitialRequest? iCurrentMsg: iWriteMsg;
       
  1175 	ASSERT(msg);
       
  1176 	
       
  1177 	TInt ret = KErrNone;
       
  1178 	TBool completeReq = ETrue;
       
  1179 	
       
  1180 	if (IsStream())
       
  1181 		{
       
  1182 		ret = FillStreamProtocol(msg);
       
  1183 
       
  1184 		if(iSendByteCount > 0)
       
  1185 			{
       
  1186 			// Still data to write - flow-off or error
       
  1187 			if(ret != KErrNone)
       
  1188 				{
       
  1189 				if(ret == KErrNoMBufs)
       
  1190 					{
       
  1191 					ret = RequestAsyncMBufAllocation(CWaitForMBufs::ECanSend, iSendByteCount);
       
  1192 					}
       
  1193 				if(ret != KErrNone)
       
  1194 					{
       
  1195 					ret = KErrNoMemory;
       
  1196 					}
       
  1197 				}
       
  1198 			if(ret == KErrNone && (iOptions & KOptBlocking))
       
  1199 				{
       
  1200 				completeReq = EFalse;
       
  1201 				}
       
  1202 			}
       
  1203 		}
       
  1204 	else	// !IsStream()
       
  1205 		{
       
  1206 		if (aInitialRequest && ((iProtocolInfo->iMessageSize!=KSocketMessageSizeNoLimit) && (iProtocolInfo->iMessageSize!=KSocketMessageSizeUndefined) && (iSendByteCount>iProtocolInfo->iMessageSize)) ||
       
  1207 					((iOptions&KOptSendBufSet) && iSendByteCount>iSendBufSize))
       
  1208 			{
       
  1209 			SetReturn(KErrTooBig);
       
  1210 			return;
       
  1211 			}
       
  1212 
       
  1213 		RMBufChain data;
       
  1214 	   	TInt nwr = KErrNone;
       
  1215 		TInt actualSendLen = 0;		// total size of data accepted by protocol upon datagram write
       
  1216 		TInt actualBufSize = 0;
       
  1217 		if(aInitialRequest || iSendData.IsEmpty())
       
  1218 			{
       
  1219 			if (iSendUseMBufs)
       
  1220 				{
       
  1221 				ret = msg->ReadMBuf(MSG_PRM(2),data);
       
  1222 				actualSendLen = data.Length();
       
  1223 				actualBufSize = data.First()->Size();
       
  1224 				}
       
  1225 			else
       
  1226 				{
       
  1227 	 			// Possible outcomes:
       
  1228 	 			//	(1) We fail to create the MBuf chain with the client data:
       
  1229 	 			//		(a) with KErrNoMbufs - we start an asynchronous allocation and treat it as a flow-off
       
  1230 	 			//		(b) with some other -ve error code - we treat this as KErrNoMemory and complete the client
       
  1231 	 			//	(2) SAP fails to write the mbuf chain:
       
  1232 	 			//		(a) with KErrNoMbufs - we start an asynchronous allocation on its behalf and treat it as a flow-off
       
  1233 	 			//		(b) with zero, ie flow-off: we don't complete client
       
  1234 	 			//		(c) with some other -ve error code - we treat this as KErrNoMemory and complete the client
       
  1235 	 			//	(3) SAP write succeeds and returns > 1 - we complete the client with KErrNone
       
  1236 				// get MBuf chain immediately, copy avoiding iSendBuf if possible
       
  1237 
       
  1238 				ret = data.Alloc(iSendByteCount + KPaddingForHeaders, iAllocator);
       
  1239 				if(ret == KErrNone)
       
  1240 					{
       
  1241 					RMBuf* first = data.First();
       
  1242 					if(first->Size() >= (iSendByteCount + KPaddingForHeaders))
       
  1243 						{
       
  1244 						// Read directly into buffer
       
  1245 						first->SetData(KPaddingForHeaders, iSendByteCount);
       
  1246 					   	TPtr8 des(NULL, 0);
       
  1247 						des.Set(first->Ptr(), iSendByteCount, iSendByteCount);
       
  1248 						ret = msg->ReadDes(MSG_PRM(2),des);
       
  1249 						actualSendLen = des.Length();
       
  1250 						actualBufSize = actualSendLen;
       
  1251 						}
       
  1252 					else
       
  1253 						{
       
  1254 						// Have to use local descriptor to avoid multiple IPC round trips
       
  1255 						TDes8* sendBuf = BorrowTemporaryBuffer(iSendByteCount);
       
  1256 						if(!sendBuf)
       
  1257 							{
       
  1258 							// We can't allocate a buffer as big as the client so risk losing data
       
  1259 							// they've indicated as precious if it overflows. Failing immediately
       
  1260 							// without trying is the compatible option
       
  1261 							ret = KErrNoMemory;
       
  1262 							}
       
  1263 						else
       
  1264 							{
       
  1265 							if(first->Length() > KPaddingForHeaders)
       
  1266 								{
       
  1267 								first->AdjustStart(KPaddingForHeaders);
       
  1268 								}
       
  1269 							else
       
  1270 								{
       
  1271 								data.TrimStart(KPaddingForHeaders);
       
  1272 								}
       
  1273 							ret = msg->ReadDes(MSG_PRM(2), *sendBuf);	// read failure exceedingly rare so don't bother checking return yet
       
  1274 							actualSendLen = sendBuf->Length();
       
  1275 							actualBufSize = actualSendLen;
       
  1276 							data.CopyIn(*sendBuf);
       
  1277 							}
       
  1278 						}
       
  1279 					}
       
  1280 				}
       
  1281 			}
       
  1282 		else
       
  1283 			{
       
  1284 			// Resume with the RMBufChain we already fabricated 
       
  1285 			data.Assign(iSendData);
       
  1286 			if (iSendUseMBufs)
       
  1287 				{
       
  1288 				actualSendLen = data.Length();
       
  1289 				actualBufSize = data.First()->Size();
       
  1290 				}
       
  1291 			else
       
  1292 				{
       
  1293 				actualSendLen = data.Length();
       
  1294 				actualBufSize = actualSendLen;
       
  1295 				}
       
  1296 			}
       
  1297 
       
  1298 		if (ret == KErrNone)
       
  1299 			{
       
  1300 			// Clear the error operation mask.  If a protocol errors the socket whilst in the
       
  1301 			// context of the CServProviderBase::Write(...) down call, we will see it below.
       
  1302 			iErrorOperationMask = 0;
       
  1303 			if (iSendToAddrIdx < 0)
       
  1304 				{
       
  1305 				nwr = iSSPData->Write(data, iSendFlags, NULL);
       
  1306 				}
       
  1307 			else
       
  1308 				{
       
  1309 				TSockAddr addr;
       
  1310 				ret = msg->ReadDes(iSendToAddrIdx, addr);
       
  1311 				if(ret == KErrNone)
       
  1312 					{
       
  1313 					nwr = iSSPData->Write(data, iSendFlags, &addr);
       
  1314 					}
       
  1315 				}
       
  1316 
       
  1317 			if (nwr == 0)
       
  1318 				{
       
  1319 				// Flow unable to accept data but not erroring
       
  1320 				completeReq = EFalse;
       
  1321 				iSendData.Assign(data);
       
  1322 				}
       
  1323 
       
  1324 			if (iErrorOperationMask & (MSessionControlNotify::EErrorSend))
       
  1325 				{
       
  1326 				// Protocol has errored the socket.  Complete the current operation with the error.
       
  1327 				// If the error is not fatal, then it is assumed to be for the current operation only,
       
  1328 				// so clear down the error.
       
  1329 				nwr = iError;
       
  1330 				completeReq = ETrue;
       
  1331 				ClearErrorIfNotFatal(); //Sets iError = 0;
       
  1332 				iErrorOperationMask = 0;
       
  1333 				iSendData.Free();
       
  1334 				}
       
  1335 
       
  1336 			if(nwr < 0)
       
  1337 				{
       
  1338 				ret = nwr;
       
  1339 				}
       
  1340 			else if(iSendXferLenIdx >= 0)
       
  1341 				{
       
  1342 				iSendOffset = actualSendLen - data.Length();
       
  1343 				}
       
  1344 			if (!iSendUseMBufs)
       
  1345 				{
       
  1346 				// nwr > 0 == Sending using RMBufChain where we have to ensure the data is
       
  1347 				// freed once the Send is succeeded
       
  1348 				// Protocols must remove buffers they want to use
       
  1349 				data.Free();
       
  1350 				}
       
  1351 			else
       
  1352 				{
       
  1353 				if (nwr > 0)
       
  1354 					{
       
  1355 					msg->InitMBuf(MSG_PRM(2));
       
  1356 					}
       
  1357 				}
       
  1358 			}
       
  1359 		if(ret != KErrNone)
       
  1360 			{
       
  1361 			if(ret == KErrNoMBufs)
       
  1362 				{
       
  1363 				ret = RequestAsyncMBufAllocation(CWaitForMBufs::ECanSend, actualBufSize);
       
  1364 				if(ret != KErrNone)
       
  1365 					{
       
  1366 					ret = KErrNoMemory;
       
  1367 					}
       
  1368 				}
       
  1369 			if(ret == KErrNone)
       
  1370 				{
       
  1371 				if(iOptions & KOptBlocking)
       
  1372 					{
       
  1373 					completeReq = EFalse;
       
  1374 					}
       
  1375 				else
       
  1376 					{
       
  1377 					ret = KErrWouldBlock;
       
  1378 					}
       
  1379 				}
       
  1380 			}
       
  1381 		}
       
  1382 
       
  1383 	if(completeReq)
       
  1384 		{
       
  1385 		// Write completed
       
  1386 		if(iSendXferLenIdx >= 0)
       
  1387 			{
       
  1388 			iXferLength() = iSendOffset;
       
  1389 			TInt lenRet = msg->WriteDes(iSendXferLenIdx, iXferLength);
       
  1390 			if(lenRet != KErrNone && ret == KErrNone)
       
  1391 				{
       
  1392 				ret = lenRet;
       
  1393 				}
       
  1394 			}
       
  1395 		// KErrBadDescriptor means that the client has already been panicked; we must
       
  1396 		// avoid further completion of this message 
       
  1397 		if(ret == KErrBadDescriptor)
       
  1398 			{
       
  1399 			iBlockedOperations&=~EBlockedWrite;
       
  1400 			}
       
  1401 		else
       
  1402 			{
       
  1403 			if(aInitialRequest)
       
  1404 				{
       
  1405 				SetReturn(ret);
       
  1406 				}
       
  1407 			else
       
  1408 				{
       
  1409 				CompleteWrite(ret);
       
  1410 				}
       
  1411 			}
       
  1412 		}
       
  1413 	else
       
  1414 		{
       
  1415 		if(aInitialRequest)
       
  1416 			{
       
  1417 			// Doesn't matter if the client has already been panicked; we're acquiring the now-NULL msg
       
  1418 			iWriteMsg->AcquireMessage(msg);
       
  1419 			SetBlockedWrite();
       
  1420 			iBlockedOperations|=EWriteFlowedOff;
       
  1421 			DontCompleteCurrentRequest();
       
  1422 			}
       
  1423 		}
       
  1424 	}
       
  1425 
       
  1426 void ASocket::RecvL(TInt aXferLenArg, TInt aAddrArg, TInt aReadByteCount, TInt aReadFlags, TBool aUseMBufs, TInt aRecvOneOrMore)
       
  1427 /**
       
  1428  Common service routine from Recv, RecvFrom and Read.
       
  1429 */
       
  1430 	{
       
  1431 	if (IsBlockedRead())
       
  1432 		{
       
  1433 		PanicSocketClient(EReadingAlready);
       
  1434 		return;
       
  1435 		}
       
  1436 
       
  1437 	if (!CheckRunningAndSetReturn())
       
  1438 		{
       
  1439 		return;
       
  1440 		}
       
  1441 
       
  1442 	if (IsConnectionOriented())
       
  1443 		{
       
  1444 		if (State()!=ESStateConnected && State()!=ESStateShuttingDown)
       
  1445 			{
       
  1446 			LOG( ESockLog::Printf(_L("ASocket %08x RecvL() KErrNotReady"), this ) );
       
  1447 			SetReturn(KErrNotReady);
       
  1448 			return;
       
  1449 			}
       
  1450 		if (iIsBound==EFalse)
       
  1451 			{
       
  1452 			if (State() == ESStateBinding)
       
  1453     			{
       
  1454     			SetReturn(KErrInUse);
       
  1455     			return;
       
  1456 				}
       
  1457 			AutoBind();
       
  1458 			}
       
  1459 		if (aAddrArg >= 0)
       
  1460 			{
       
  1461 			SetReturn(KErrNotSupported);
       
  1462 			return;
       
  1463 			}
       
  1464 		}
       
  1465 
       
  1466 	iRecvOneOrMore = aRecvOneOrMore;
       
  1467 	if(iRecvOneOrMore && !IsStream())
       
  1468 		{
       
  1469 		SetReturn(KErrNotSupported);
       
  1470 		return;
       
  1471 		}
       
  1472 
       
  1473 	// Set whether we are going to receive in RMBufChain way
       
  1474 	iRecvUseMBufs = aUseMBufs;
       
  1475 
       
  1476 	iRecByteCount=aReadByteCount;
       
  1477     if(iRecByteCount<0)
       
  1478         {
       
  1479         PanicSocketClient(EBadDescriptorLength);
       
  1480         User::Leave(KErrBadDescriptor);
       
  1481         }
       
  1482 	iRecvFlags=aReadFlags;
       
  1483 	if(iRecvFlags)
       
  1484 	    {
       
  1485         if(iRecvFlags&KSocketInternalReadBit)
       
  1486             {
       
  1487             SetReturn(KErrAccessDenied);
       
  1488             return;
       
  1489             }
       
  1490         if (iRecvFlags&KSockReadPeek && !SupportsPeek())
       
  1491             {
       
  1492             SetReturn(KErrNotSupported);
       
  1493             return;
       
  1494             }
       
  1495 	    }
       
  1496 	iRecvFromAddrIdx = aAddrArg;
       
  1497 	iRecvXferLenIdx=aXferLenArg;
       
  1498 
       
  1499 #ifdef SYMBIAN_NETWORKING_PERFMETRICS
       
  1500 	IncludePerformanceData(-1, iRecByteCount, -1);
       
  1501 #endif
       
  1502 
       
  1503 	iRecOffset=0;
       
  1504 	DoRecv(ETrue);
       
  1505 	}
       
  1506 
       
  1507 void ASocket::DoRecv(TBool aInitialRequest)
       
  1508 	{
       
  1509 	AMessage* msg = aInitialRequest? iCurrentMsg: iReadMsg;
       
  1510 
       
  1511 	if(aInitialRequest || IsBlockedRead())
       
  1512 		{
       
  1513 		TInt errReadProtocol = KErrNone;
       
  1514 		TBool completeReq = ETrue;
       
  1515 	
       
  1516 		if((iBlockedOperations&EReadStopped) && iDataAvailable<=0)
       
  1517 			{
       
  1518 			TInt ret = msg->WriteDes(MSG_PRM(2), KNullDesC8);
       
  1519 			iRecOffset = 0;
       
  1520 			errReadProtocol = KErrEof;
       
  1521 			}
       
  1522 		else if (IsStream())
       
  1523 		    {
       
  1524 			errReadProtocol = DrainStreamProtocol(msg);
       
  1525 			if(errReadProtocol == KErrNone)
       
  1526 			    {
       
  1527 				if(iRecvOneOrMore && iRecOffset > 0) // i.e. data received
       
  1528                     {
       
  1529                     iRecByteCount=0;
       
  1530                     }
       
  1531 				if (iRecByteCount>0) // Still data expected
       
  1532                     {
       
  1533                     if(!(iBlockedOperations&EReadStopped) || iDataAvailable>0)
       
  1534                         {
       
  1535                         if ((iOptions&KOptBlocking))
       
  1536                             {
       
  1537 			    // This error condition can never be reached under the current structure. Further investigation into how other teams,
       
  1538 			    // such as Bluetooth, handle memory errors in this situation is needed before restructuring this method.
       
  1539 
       
  1540                             //if(errReadProtocol == KErrNoMBufs)
       
  1541                             //    {
       
  1542                             //    // Block unless request fails
       
  1543 							//	errReadProtocol = RequestAsyncMBufAllocation(CWaitForMBufs::ENewData, iRecByteCount/*iRecBuf.MaxLength()*/) == KErrNone;
       
  1544 							//	completeReq = errReadProtocol == KErrNone;
       
  1545                             //    }
       
  1546                             //else
       
  1547                             if(iError != KErrNone)
       
  1548                                 {
       
  1549                                 // Don't block as protocol is already erroring client
       
  1550 								errReadProtocol = iError;
       
  1551                                 // If the socket error is not fatal, then reset it so that only the current
       
  1552                                 // receive operation is completed with the error (not every subsequent one).
       
  1553                                 ClearErrorIfNotFatal();
       
  1554                                 }
       
  1555                             else
       
  1556                                 {
       
  1557                                 completeReq = EFalse;
       
  1558                                 }
       
  1559                             }
       
  1560                         else
       
  1561                             {
       
  1562                             errReadProtocol = KErrWouldBlock;
       
  1563                             }
       
  1564                         }
       
  1565 					else
       
  1566 						{
       
  1567 						errReadProtocol = KErrEof;
       
  1568 						}
       
  1569                     }
       
  1570 			    }
       
  1571 		    }
       
  1572 		else
       
  1573 			{	// !IsStream()
       
  1574 
       
  1575 			// If the previous call to Recv used the KSockReadContinuation method and left iDatagramTail empty (everything
       
  1576 			// up to the end of the packet was read) then tailContinuation will be false this time round - this will cause
       
  1577 			// the reading of new data from iSSP below.
       
  1578 			TBool tailContinuation = (iRecvFlags & KSockReadContinuation) != 0 && !iDatagramTail.IsEmpty();
       
  1579 			TBool needToBlock = !tailContinuation && iDataAvailable <= 0;
       
  1580 			errReadProtocol = KErrNone;
       
  1581 	
       
  1582 			if(aInitialRequest)
       
  1583 				{
       
  1584 				//-- if we have a read from the socket with flag  KSockReadPeek set
       
  1585 				//-- and if we need to block, set the NewData() recursion counter to 1.
       
  1586 				//-- otherwise, reset it, it will not be checked then.
       
  1587 				if(needToBlock && (iRecvFlags & KSockReadPeek))
       
  1588 					{
       
  1589 					iBlockOnPeekReadCnt = 1;
       
  1590 					}
       
  1591 				else
       
  1592 					{
       
  1593 					iBlockOnPeekReadCnt = 0;
       
  1594 					}
       
  1595 				}	
       
  1596 	
       
  1597 			if (!needToBlock)
       
  1598 				{
       
  1599 				TDes8* recBuf = BorrowTemporaryBuffer(iRecByteCount);
       
  1600 				if(!recBuf)
       
  1601 					{
       
  1602 					// We can't allocate a buffer as big as the client so risk losing data
       
  1603 					// they've indicated as precious if it overflows. Failing immediately
       
  1604 					// without trying is the compatible option
       
  1605 					errReadProtocol = KErrNoMemory;
       
  1606 					}
       
  1607 				// Only read from the provider if we can't use the previous tail
       
  1608 				else if(!tailContinuation)
       
  1609 					{
       
  1610 					// Free it only if the chain is empty. For RMBufChain read, the receiveer must have been freed it.
       
  1611 					// and we don't need to free it
       
  1612 					if(!iDatagramTail.IsEmpty() && !iRecvUseMBufs)
       
  1613 						{
       
  1614 						iDatagramTail.Free();
       
  1615 						}
       
  1616 					if (iRecvFromAddrIdx < 0)
       
  1617 						{
       
  1618 						errReadProtocol = iSSPData->GetData(iDatagramTail, iRecByteCount | KGetDataWholeDatagram, iRecvFlags);
       
  1619 						}
       
  1620 					else
       
  1621 						{
       
  1622 						errReadProtocol = iSSPData->GetData(iDatagramTail, iRecByteCount | KGetDataWholeDatagram, iRecvFlags, &iRecvFromAddr);
       
  1623 						}
       
  1624 					}
       
  1625 				// Protocols must either deliver the request or return an error and deliver nothing
       
  1626 				//__ASSERT_DEBUG( (errReadProtocol < 0 && data.IsEmpty()), Panic(EBadDataCount));
       
  1627 				TInt trimTailAmount = 0;
       
  1628 				if(errReadProtocol < 0)
       
  1629 					{
       
  1630 					// Protocol has failed to deliver, so we'll have to block. If it's a KErrNoMBufs (a likely case) then we kick off
       
  1631 					// an asynch allocation for amount and upon its completion try again. Of course we cannot know whether this is the
       
  1632 					// number of mbufs that the protocol wanted but it's a good guess. If it's some other error then it's up to the
       
  1633 					// protocol to tell us when to retry (by signalling with NewData(0)). If it was some error that the protocol
       
  1634 					// couldn't handle at all then it should have set the error upon the socket rather than expecting us to magically
       
  1635 					// "do the right thing"
       
  1636 					needToBlock = ETrue;
       
  1637 					}
       
  1638 				else
       
  1639 					{
       
  1640 					if (iRecvUseMBufs)
       
  1641 						{
       
  1642 						// We don't trim anything, when we do a RMBufChain read with KSockReadPeek is set
       
  1643 						// KSockReadPeek is upto the SAP shim
       
  1644 						errReadProtocol = msg->WriteMBuf(MSG_PRM(2),iDatagramTail);
       
  1645 						if(errReadProtocol == KErrNone)
       
  1646 							{
       
  1647 							iDatagramTail.Init();
       
  1648 							// Just remove the chain that we have given back from the tail. When using MBufs the
       
  1649 							// client always gets the entire datagram anyway (the datagram tail mechanism is there
       
  1650 							// just so someone using a descriptor can do a continuation read if it overflows, so they
       
  1651 							// don't have to use 64k buffer just in case some loony soaks them with a jumbogram).
       
  1652 							// So there's no trimming done & no need to discriminate between peek & normal.
       
  1653 							}
       
  1654 						}
       
  1655 					else
       
  1656 						{
       
  1657 						TPtr8 des(recBuf->MidTPtr(0, iRecByteCount));
       
  1658 	
       
  1659 						if (!iDatagramTail.IsEmpty())
       
  1660 							{
       
  1661 							// intermediate descriptor copy
       
  1662 							RMBuf* first = iDatagramTail.First();
       
  1663 							if(!first->Next())
       
  1664 								{
       
  1665 								TInt copyLen = Min(first->Length(), iRecByteCount);
       
  1666 								des.Set(first->Ptr(), copyLen, copyLen);
       
  1667 								}
       
  1668 							else
       
  1669 								{
       
  1670 								iDatagramTail.CopyOut(des, 0);
       
  1671 								}
       
  1672 							}
       
  1673 						else
       
  1674 							{
       
  1675 							des.SetLength(0);
       
  1676 							}
       
  1677 						errReadProtocol = msg->WriteDes(MSG_PRM(2),des);
       
  1678 						if((errReadProtocol == KErrNone && iRecvFlags & KSockReadPeek) == 0)
       
  1679 							{
       
  1680 							// Note the amount of data to trim after writing it to the client
       
  1681 							trimTailAmount = des.Length();
       
  1682 							}
       
  1683 						}
       
  1684 	
       
  1685 	#ifdef SYMBIAN_NETWORKING_PERFMETRICS
       
  1686 					IncludePerformanceData(trimTailAmount, -1, -1);
       
  1687 	#endif
       
  1688 	
       
  1689 					if(errReadProtocol == KErrNone)
       
  1690 						{
       
  1691 						if (trimTailAmount != 0)
       
  1692 							{
       
  1693 							iDatagramTail.TrimStart(trimTailAmount);
       
  1694 							}
       
  1695 						if(iRecvXferLenIdx >= 0)
       
  1696 							{
       
  1697 							// Number of bytes remaining. (store for later write)
       
  1698 							iRecOffset = iDatagramTail.Length();
       
  1699 							}
       
  1700 						if(iRecvFromAddrIdx >= 0)
       
  1701 							{
       
  1702 							errReadProtocol = msg->WriteDes(iRecvFromAddrIdx, iRecvFromAddr);
       
  1703 							}
       
  1704 						if(errReadProtocol == KErrNone && !tailContinuation)
       
  1705 							{
       
  1706 							// When using a non-stream based socket the value iDataAvailable refers to the number of packets available.
       
  1707 							// In the case where tail continuation is in use the packet may not fully have been dealt with yet (more
       
  1708 							// could be read from it next time) and so the value should not be decremented yet. This is the case even
       
  1709 							// if all the data up to the end of the packet has been read (the above call to TrimStart will leave
       
  1710 							// iDatagramTail empty and then on the next call of this method tailContinuation will be set to false).
       
  1711 							iDataAvailable--;
       
  1712 							}
       
  1713 						}
       
  1714 					}
       
  1715 				}
       
  1716 	
       
  1717 			if(needToBlock)
       
  1718 				{
       
  1719 				if (iOptions & KOptBlocking)
       
  1720 					{
       
  1721 					if (errReadProtocol == KErrNoMBufs)
       
  1722 						{
       
  1723 						// Block unless request fails
       
  1724 						needToBlock = RequestAsyncMBufAllocation(CWaitForMBufs::ENewData, iRecByteCount) == KErrNone;
       
  1725 						}
       
  1726 					else if (iError != KErrNone)
       
  1727                         {
       
  1728                         // Don't block as protocol is already erroring client
       
  1729                         needToBlock = EFalse;
       
  1730                         errReadProtocol = iError;
       
  1731                         // If the socket error is not fatal, then reset it so that only the current
       
  1732                         // receive operation is completed with the error (not every subsequent one).
       
  1733                         ClearErrorIfNotFatal();
       
  1734                         }
       
  1735                     else if (errReadProtocol != KErrNone)
       
  1736                         {
       
  1737                         needToBlock = EFalse;
       
  1738 						}
       
  1739 					completeReq = !needToBlock;
       
  1740 					}
       
  1741 				else
       
  1742 					{
       
  1743 					errReadProtocol = KErrWouldBlock;
       
  1744 					}
       
  1745 				}
       
  1746 			}
       
  1747 		
       
  1748 		if(completeReq)
       
  1749 			{
       
  1750 			// Read completed
       
  1751 			if(iRecvXferLenIdx >= 0)
       
  1752 				{
       
  1753 				iXferLength() = iRecOffset;
       
  1754 				TInt ret = msg->WriteDes(iRecvXferLenIdx, iXferLength);
       
  1755 				if(ret != KErrNone && errReadProtocol == KErrNone)
       
  1756 					{
       
  1757 					errReadProtocol = ret;
       
  1758 					}
       
  1759 				}
       
  1760 			// KErrBadDescriptor means that the client has already been panicked; we must
       
  1761 			// avoid further completion of this message 
       
  1762 			if(errReadProtocol == KErrBadDescriptor)
       
  1763 				{
       
  1764 				iBlockedOperations&=~EBlockedRead;
       
  1765 				}
       
  1766 			else
       
  1767 				{
       
  1768 				if(aInitialRequest)
       
  1769 					{
       
  1770 					SetReturn(errReadProtocol);
       
  1771 					}
       
  1772 				else
       
  1773 					{
       
  1774 					CompleteRead(errReadProtocol);
       
  1775 					}
       
  1776 				}
       
  1777 			}
       
  1778 		else
       
  1779 			{
       
  1780 			if(aInitialRequest)
       
  1781 				{
       
  1782 				// Doesn't matter if the client has already been panicked; we're acquiring the now-NULL msg
       
  1783 				iReadMsg->AcquireMessage(msg);
       
  1784 				SetBlockedRead();
       
  1785 				DontCompleteCurrentRequest();
       
  1786 				}
       
  1787 			}
       
  1788 		}
       
  1789     TryToCompleteSelectIoctl();
       
  1790 	}
       
  1791 
       
  1792 void ASocket::ListenL(TInt aQlen, TBool aConnectionData)
       
  1793 /**
       
  1794 Listen request service
       
  1795 Listen is a dead and, clients can't do anything with the socket other than Accept after a listen.
       
  1796 */
       
  1797 	{
       
  1798 
       
  1799 	switch (State())
       
  1800 		{
       
  1801 	case ESStateConnected:
       
  1802 	case ESStateOpeningActive:
       
  1803 	case ESStateBinding:
       
  1804 		SetReturn(KErrInUse);
       
  1805 		return;
       
  1806 	case ESStateOpeningPassive:
       
  1807 		PanicSocketClient(EAlreadyListening);
       
  1808 		//lint -fallthrough
       
  1809 	case ESStateShuttingDown:
       
  1810 	case ESStateClosing:
       
  1811 	case ESStateDead:
       
  1812 		SetReturn(KErrBadHandle);
       
  1813 		return;
       
  1814 	case ESStateDisconnected:
       
  1815 		SetReturn(KErrDisconnected);
       
  1816 		return;
       
  1817 	case ESStateError:
       
  1818 		SetReturn(iError);
       
  1819 		return;
       
  1820 	case ESStateNull:
       
  1821 	case ESStateAccepting:
       
  1822 		PanicSocketClient(ESockBadHandle);
       
  1823 		return;
       
  1824 	case ESStateCreated:
       
  1825 	case ESStateOpen:
       
  1826 	default:
       
  1827 		break;
       
  1828 		}
       
  1829 
       
  1830 	if (!IsConnectionOriented())
       
  1831 		{
       
  1832 		PanicSocketClient(EListenNeedsConnection);
       
  1833 		return;
       
  1834 		}
       
  1835 
       
  1836 	if (!iIsBound)
       
  1837 		{
       
  1838 		SetReturn(KErrBadName);
       
  1839 		return;
       
  1840 		}
       
  1841 
       
  1842 	if(!iAcceptQ)
       
  1843 		{
       
  1844 		iAcceptQ = new (ELeave) CCirBuf<TAcceptQEntry>;
       
  1845 		}
       
  1846 	CleanupStack::PushL(iAcceptQ);
       
  1847 	iAcceptQ->SetLengthL(aQlen);
       
  1848 
       
  1849 	// Create a second queue we can transfer the contents to if we need to remove an SAP
       
  1850 	// from the middle of the ring buffer.
       
  1851 	if(!iNextAcceptQ)
       
  1852 		{
       
  1853 		iNextAcceptQ = new (ELeave) CCirBuf<TAcceptQEntry>;
       
  1854 		}
       
  1855 	CleanupStack::PushL(iNextAcceptQ);
       
  1856 	iNextAcceptQ->SetLengthL(aQlen);
       
  1857 
       
  1858 	TInt ret;
       
  1859 	if (aConnectionData)
       
  1860 		{
       
  1861 		TDes8& xferBuf = *BorrowTemporaryBufferL(iSendBufSize);
       
  1862 		xferBuf.SetLength(iSendBufSize);
       
  1863 		ReadParamL(ESocketCurrentMessage, MSG_PRM(1), xferBuf);
       
  1864 		ret=iSSP->PassiveOpen(aQlen, xferBuf);
       
  1865 		}
       
  1866 	else
       
  1867 		{
       
  1868 		ret=iSSP->PassiveOpen(aQlen);
       
  1869 		}
       
  1870 
       
  1871 	if (ret==KErrNone)
       
  1872 		{
       
  1873 		SetState(ESStateOpeningPassive);
       
  1874 		}
       
  1875 	else
       
  1876 		{
       
  1877 		SetReturn(ret);
       
  1878 		}
       
  1879 
       
  1880 	CleanupStack::Pop(iNextAcceptQ);
       
  1881 	CleanupStack::Pop(iAcceptQ);
       
  1882 	}
       
  1883 
       
  1884 void ASocket::Accept()
       
  1885 /**
       
  1886 Accept a connection on a listening socket.
       
  1887 */
       
  1888 	{
       
  1889 
       
  1890 	if ( State()!=ESStateOpeningPassive ) // protocol may have generated an error on the accept
       
  1891 	    {                    // SAP for some bizzare reason. We can't test just (State()==ESStateError)
       
  1892 		                     // 'cos if reconnection iState could be whatever (see ASocket::Error)
       
  1893                              //so check if we'r listenning at all
       
  1894         SetReturn(iError != KErrNone ? iError : KErrNotReady);
       
  1895 		return;
       
  1896 	    }
       
  1897 
       
  1898 	if ( !iAcceptQ || !iNextAcceptQ )
       
  1899 		{
       
  1900 		PanicSocketClient(ENotListening);
       
  1901 		return;
       
  1902 		}
       
  1903 
       
  1904 	if (IsBlockedConnect())
       
  1905 		{
       
  1906 		PanicSocketClient(EAcceptTwice);
       
  1907 		return;
       
  1908 		}
       
  1909 
       
  1910 
       
  1911 	ASocket* acceptingSocket = InitiateAcceptingSocket();
       
  1912 
       
  1913 	if ( !acceptingSocket ) // The acceptingSocket will be NULL if we got a panic. return here.
       
  1914 		return;
       
  1915 
       
  1916 	if (!iAcceptQ->Count())
       
  1917 		{
       
  1918 		if (!(iOptions & KOptBlocking))
       
  1919 			{
       
  1920 			SetReturn(KErrWouldBlock);
       
  1921 			return;
       
  1922 			}
       
  1923 
       
  1924 		SetBlockedConnect();
       
  1925 		DontCompleteCurrentRequest();
       
  1926 		return;
       
  1927 		}
       
  1928 
       
  1929 	// If the queue isn't empty setting the blocked connect and calling DoCompleteAccept will work it's magic - this saves us code
       
  1930 	SetBlockedConnect();
       
  1931 	DoCompleteAccept();
       
  1932 	DontCompleteCurrentRequest();	// Don't want to complete twice.
       
  1933 	}
       
  1934 
       
  1935 void ASocket::LocalNameL()
       
  1936 /**
       
  1937 Get local name for a client request
       
  1938 */
       
  1939 	{
       
  1940 
       
  1941 	if (!CheckRunningAndSetReturn())
       
  1942 		{
       
  1943 		return;
       
  1944 		}
       
  1945 
       
  1946 	if (!iIsBound)
       
  1947 		{
       
  1948 		SetReturn(KErrNotFound);
       
  1949 		return;
       
  1950 		}
       
  1951 	else
       
  1952 		{
       
  1953 		TSockAddr addr;
       
  1954 		iSSP->LocalName(addr);
       
  1955 		WriteParamL(ESocketCurrentMessage,MSG_PRM(0),addr);
       
  1956 		}
       
  1957 
       
  1958 	}
       
  1959 
       
  1960 void ASocket::RemoteNameL()
       
  1961 /**
       
  1962 Get remote name for a cleient request
       
  1963 */
       
  1964 	{
       
  1965 
       
  1966 	if (!CheckRunningAndSetReturn())
       
  1967 		{
       
  1968 		return;
       
  1969 		}
       
  1970 
       
  1971 	if (State()==ESStateConnected || State()==ESStateOpeningActive || State()==ESStateShuttingDown)
       
  1972 		{
       
  1973 		TSockAddr addr;
       
  1974 		iSSP->RemName(addr);
       
  1975 		WriteParamL(ESocketCurrentMessage,MSG_PRM(0),addr);
       
  1976 		}
       
  1977 	else
       
  1978 		{
       
  1979 		SetReturn(KErrNotFound);
       
  1980 		return;
       
  1981 		}
       
  1982 	}
       
  1983 
       
  1984 void ASocket::NewData(TUint aCount)
       
  1985 /**
       
  1986 Called from a protocol to indicate that new data is available for reading
       
  1987 
       
  1988 */
       
  1989 	{
       
  1990 	__ASSERT_DEBUG(State()!=ESStateDead,Panic(EBadStateUpCall));
       
  1991 //	__ASSERT_DEBUG(State()!=ESStateCreated,Panic(EBadStateUpCall));		// no longer forced into shuttingdown state upon half-close
       
  1992 	__ASSERT_DEBUG(State()!=ESStateClosing,Panic(EBadStateUpCall));
       
  1993 	__ASSERT_DEBUG(!(iBlockedOperations&EReadStopped),Panic(EBadStateUpCall));
       
  1994 	__ASSERT_DEBUG(State()!=ESStateError,Panic(EBadStateUpCall));
       
  1995 	__ASSERT_DEBUG(State()!=ESStateDisconnected,Panic(EBadStateUpCall));
       
  1996 // zero is used in v1.5 to resume after	reneging __ASSERT_DEBUG(aCount>0,Panic(EBadDataCount));
       
  1997 
       
  1998 	if(aCount==KNewDataEndofData)
       
  1999 		{
       
  2000 		iBlockedOperations |= EReadStopped;
       
  2001 		}
       
  2002 	else
       
  2003 		{
       
  2004 		iDataAvailable+=aCount;
       
  2005 		__ASSERT_DEBUG(iDataAvailable>=0,Panic(EBadDataCount));
       
  2006 		}
       
  2007 
       
  2008     //-- check the recursion level counter.
       
  2009     //-- if it is 0, there were no recursion entry to itself, continue.
       
  2010     //-- if it is 1, there was blocked read from socket with KSockReadPeek set, increase it and continue.
       
  2011     //-- if it is 2, it means that function has been called from itself via NewData()-> [iSSP->CetData()] -> NewData()
       
  2012     //-- return to stop the infinite recursion.
       
  2013     if(iBlockOnPeekReadCnt >0)
       
  2014         {
       
  2015         if(iBlockOnPeekReadCnt >= 2)
       
  2016             {
       
  2017             iBlockOnPeekReadCnt = 0;
       
  2018             return;
       
  2019             }
       
  2020         else
       
  2021             {
       
  2022             iBlockOnPeekReadCnt ++;
       
  2023             }
       
  2024 	    }
       
  2025 
       
  2026     DoRecv(EFalse);
       
  2027 	}
       
  2028 
       
  2029 void ASocket::CanSend()
       
  2030 /**
       
  2031 Called from protocol to indicate new buffer space has become available
       
  2032 */
       
  2033 	{
       
  2034 	__ASSERT_DEBUG(State()!=ESStateDead,Panic(EBadStateUpCall));
       
  2035 	__ASSERT_DEBUG(State()!=ESStateCreated,Panic(EBadStateUpCall));
       
  2036 	__ASSERT_DEBUG(State()!=ESStateClosing,Panic(EBadStateUpCall));
       
  2037 	__ASSERT_DEBUG(State()!=ESStateShuttingDown,Panic(EBadStateUpCall));
       
  2038 	__ASSERT_DEBUG(State()!=ESStateError,Panic(EBadStateUpCall));
       
  2039 	__ASSERT_DEBUG(State()!=ESStateDisconnected,Panic(EBadStateUpCall));
       
  2040 
       
  2041 	TBool writeflowedoff = iBlockedOperations&EWriteFlowedOff;
       
  2042 	iBlockedOperations &= ~EWriteFlowedOff;
       
  2043 	if(IsBlockedWrite())
       
  2044 		{
       
  2045 		DoSend(EFalse);
       
  2046 		}
       
  2047 	if(writeflowedoff && !(iBlockedOperations&EWriteFlowedOff))
       
  2048 		{
       
  2049 		TryToCompleteSelectIoctl();
       
  2050 		}
       
  2051 	}
       
  2052 
       
  2053 
       
  2054 void ASocket::ConnectComplete()
       
  2055 /**
       
  2056 Called from protocol to indicate that an active open has completed
       
  2057 */
       
  2058 	{
       
  2059 	//__ASSERT_DEBUG(State()==ESStateOpeningActive,Panic(EBadStateUpCall));
       
  2060 	if (IsConnectionOriented())
       
  2061 		{
       
  2062 		SetState(ESStateConnected);
       
  2063 		//__ASSERT_DEBUG(IsBlockedConnect(), Panic(EUnexpectedConnect));
       
  2064 		// assertion is invalid because operation could have been cancelled MarkT
       
  2065 		CompleteConnect(KErrNone);
       
  2066 		}
       
  2067 	TryToCompleteSelectIoctl();
       
  2068 	}
       
  2069 
       
  2070 void ASocket::ConnectComplete(const TDesC8& aConnectData)
       
  2071 /**
       
  2072 Called from protocol to indicate that an active open has completed with connection data
       
  2073 */
       
  2074 	{
       
  2075 	__ASSERT_ALWAYS(CanSendConnectData(),Panic(EUnexpectedConnectData));
       
  2076 	//__ASSERT_DEBUG(IsBlockedConnect(),Panic(EUnexpectedConnect));
       
  2077 	// assertion is invalid because operation could have been cancelled
       
  2078 	if ( !iBlockedConnectMsg->IsNull (MSG_PRM(2)) )
       
  2079 		{
       
  2080 		TInt ret = iBlockedConnectMsg->WriteDes(MSG_PRM(2),aConnectData);
       
  2081 		if(ret!= KErrNone)
       
  2082 			{
       
  2083 			return;
       
  2084 			}
       
  2085 		}
       
  2086 	ConnectComplete();
       
  2087 	}
       
  2088 
       
  2089 void ASocket::ConnectComplete(CSubConnectionFlowBase& anSSP)
       
  2090 /**
       
  2091 Called from protocol to indicate that a passive open has completed
       
  2092 */
       
  2093 	{
       
  2094 	__ASSERT_DEBUG(State()==ESStateOpeningPassive,Panic(EBadStateUpCall));
       
  2095 	__ASSERT_ALWAYS(iAcceptQ, Panic(ENotListeningSocket));
       
  2096 	__ASSERT_ALWAYS(iAcceptQ->Count()<iAcceptQ->Length(), Panic(EAcceptQueFull));
       
  2097 
       
  2098 	TAcceptQEntry n;
       
  2099 	n.iSSP = &anSSP;
       
  2100 	n.iConnectData=NULL;
       
  2101 	n.iConnectDataError=KErrNone;
       
  2102 	iAcceptQ->Add(&n);
       
  2103 
       
  2104 	DoCompleteAccept();
       
  2105 	//LOG( ESockLog::Printf(_L("ASocket::ConnectComplete iAcceptQ->=%d, provider =%u)"), iAcceptQ->Count(), (void*)&anSSP ) );
       
  2106 	TryToCompleteSelectIoctl();
       
  2107 	}
       
  2108 
       
  2109 void ASocket::ConnectComplete(CSubConnectionFlowBase& anSSP,const TDesC8& aConnectData)
       
  2110 /**
       
  2111 Called from protocol to indicate that a passive open has completed with connection data
       
  2112 */
       
  2113 	{
       
  2114 	__ASSERT_ALWAYS(CanSendConnectData(),Panic(EUnexpectedConnectData));
       
  2115 	__ASSERT_ALWAYS(iAcceptQ, Panic(ENotListeningSocket));
       
  2116 	__ASSERT_ALWAYS(iAcceptQ->Count()<iAcceptQ->Length(), Panic(EAcceptQueFull));
       
  2117 
       
  2118 	TAcceptQEntry n;
       
  2119 	n.iSSP = &anSSP;
       
  2120 	n.iConnectDataError = KErrNone;
       
  2121 	n.iConnectData=aConnectData.Alloc();
       
  2122 	if(!n.iConnectData)
       
  2123 		{
       
  2124 		n.iConnectDataError = KErrNoMemory;
       
  2125 		}
       
  2126 	iAcceptQ->Add(&n);
       
  2127 
       
  2128 	DoCompleteAccept();
       
  2129 	TryToCompleteSelectIoctl();
       
  2130 	}
       
  2131 
       
  2132 void ASocket::DoCompleteAccept()
       
  2133 /**
       
  2134 Common dequeue for accept upcalls
       
  2135 */
       
  2136 	{
       
  2137 	__ASSERT_DEBUG(iAcceptQ->Count(),Fault(EBadAcceptQueue));
       
  2138 
       
  2139 	if (!IsBlockedConnect())
       
  2140 		{
       
  2141 		return;
       
  2142 		}
       
  2143 
       
  2144     TAcceptQEntry a;
       
  2145 	iAcceptQ->Remove(&a);
       
  2146 
       
  2147 	ASocket* newCon=GetAcceptingSocket();
       
  2148 	CTransportFlowShim* shimFlow = factoryobject_cast<CTransportFlowShim>(a.iSSP);
       
  2149 	__ASSERT_DEBUG(shimFlow, User::Panic(KSpecAssert_ESockSSocksntsck, 6));
       
  2150 
       
  2151 	// The SAP is no longer owned by the listener socket.
       
  2152 	shimFlow->iListenerControlNotify = NULL;
       
  2153 
       
  2154 	if (newCon == NULL)
       
  2155 		{
       
  2156 		// Delete the flow created for accept
       
  2157 		shimFlow->InitDestroy();
       
  2158 		CompleteConnect(KErrCancel);
       
  2159 		return;
       
  2160 		}
       
  2161 
       
  2162 	TRAPD(ret, newCon->AcceptSetupL(*this,*a.iSSP));
       
  2163 	//!!!there was a defect where by deleting iSSP here the TCP PRT would crash. Steve Butler
       
  2164 	//fixed it => check it snce aiSSP would be deleted had AcceptSetupL left!!!
       
  2165 	if (ret != KErrNone)
       
  2166 		{
       
  2167 		CompleteConnect(ret);
       
  2168 		return;
       
  2169 		}
       
  2170 /* goes into AcceptSetupL vitual fn
       
  2171 	if (newCon->State()!=ESStateAccepting && newCon->State()!=ESStateNull)
       
  2172 		{
       
  2173 		//Session()->PanicSocketClient(iBlockedConnect,KESockClientPanic,EBadAccept);
       
  2174 		CWorkerSession::PanicSocketClient(iBlockedConnect,KESockClientPanic,EBadAccept);
       
  2175 		iSession->DontCompleteCurrentRequest();
       
  2176 		return;
       
  2177 		}
       
  2178 */
       
  2179 	newCon->SetState(ESStateConnected);
       
  2180 
       
  2181 	if (a.iConnectData)// && iBlockedConnect.Ptr2()) checked in WriteParam
       
  2182 		{
       
  2183 		TPtr8 des=a.iConnectData->Des();
       
  2184 		ret = iBlockedConnectMsg->WriteDes(MSG_PRM(2),des,0);
       
  2185 		if(ret!= KErrNone)
       
  2186 			{
       
  2187 			return;
       
  2188 			}
       
  2189 		}
       
  2190 
       
  2191 	delete a.iConnectData;
       
  2192 
       
  2193 	// Call SecurityCheck() on the new SAP to communicate the MProvdSecurityChecker
       
  2194 	// pointer to it.  It is a somewhat bizarre situation if the PRT returns an error
       
  2195 	// to this as, in reality, the PRT  should not make a ConnectComplete() upcall in the
       
  2196 	// first place only to fail the subsequent SecurityCheck() downcall.  The PRT should check
       
  2197 	// security beforehand and, on failure, simply not call ConnectComplete().  However, if we
       
  2198 	// get an error, then complete the RSocket::Accept() operation on the listening socket with
       
  2199 	// the error and place the accept socket in the error state.
       
  2200 	ret = newCon->SecurityCheck();
       
  2201 	if (ret != KErrNone)
       
  2202 		{
       
  2203 		LOG( ESockLog::Printf(_L("ASocket %08x:\tDoCompleteAccept(): socket %08x returned security check error %d"), this, a.iSSP, ret ) );
       
  2204 		a.iConnectDataError = ret;
       
  2205 		newCon->Error(ret, MSessionControlNotify::EErrorFatal);
       
  2206 		}
       
  2207 
       
  2208 	newCon->iSSP->Start();
       
  2209 	CompleteConnect(a.iConnectDataError);
       
  2210 	}
       
  2211 
       
  2212 void ASocket::CanClose(MSessionControlNotify::TDelete aDelete)
       
  2213 /**
       
  2214 Called from protocol to indicate that a graceful close has completed
       
  2215 */
       
  2216 	{
       
  2217 	(void)aDelete;
       
  2218 
       
  2219 	//__ASSERT_ALWAYS(IsBlockedClose(),Panic(EUnexpectedClose));
       
  2220 	// assertion is invalid because operation could have been cancelled MarkT
       
  2221 	__ASSERT_DEBUG(State()==ESStateClosing||State()==ESStateShuttingDown,Panic(EBadStateUpCall));
       
  2222 
       
  2223 	CompleteClose(KErrNone);
       
  2224 	if (iFlowBinder)
       
  2225 		{
       
  2226 		iFlowBinder->Unbind();
       
  2227 		}
       
  2228 	// Flowbinder takes care of itself from now onwards; forget all downwards pointers
       
  2229 	iSSP = NULL;
       
  2230 	iSSPData = NULL;
       
  2231 	iFlowBinder = NULL;
       
  2232 	iServiceProvider.Close();
       
  2233 /* Flow binder takes care of this SAP behaviour
       
  2234 	if(aDelete==MSessionControlNotify::EDetach)
       
  2235 	    {
       
  2236 		iSSP = NULL;		// Stop d'tor deleting the SSP.
       
  2237 		iFlowBinder = NULL;iSSPData = NULL;
       
  2238 		}
       
  2239 */
       
  2240 	if (State()==ESStateClosing)
       
  2241 		{
       
  2242 		SetState(ESStateDead);
       
  2243 
       
  2244 		// delete this; must not access member data after executing this statement
       
  2245 	    InitiateDestruction();
       
  2246 		}
       
  2247 	else
       
  2248 	    {
       
  2249 		SetState(ESStateDead);
       
  2250 		}
       
  2251 
       
  2252 	}
       
  2253 
       
  2254 void ASocket::CanClose(const TDesC8& aDisconnectData, MSessionControlNotify::TDelete aDelete)
       
  2255 /**
       
  2256 Called from protocol to indicate that a graceful close has completed with disconnect data
       
  2257 */
       
  2258 	{
       
  2259 
       
  2260 	//__ASSERT_ALWAYS(IsBlockedClose(),Panic(EUnexpectedClose));
       
  2261 	// assertion is invalid because operation could have been cancelled MarkT
       
  2262 	// or could be non-blocking close
       
  2263 	__ASSERT_ALWAYS(CanSendDisconnectData(),Panic(EUnexpectedDisconnectData));
       
  2264 	TInt ret = iBlockedCloseMsg->WriteDes(MSG_PRM(2),aDisconnectData);
       
  2265 	if(ret!= KErrNone)
       
  2266 		{
       
  2267 		return;
       
  2268 		}
       
  2269 	CanClose(aDelete);
       
  2270 	}
       
  2271 
       
  2272 void ASocket::Disconnect()
       
  2273 /**
       
  2274 Called from protocol to indicate that a disconnect has been initiated - prob from the remote host
       
  2275 */
       
  2276 	{
       
  2277 	__ASSERT_ALWAYS(IsConnectionOriented(),Panic(EBadDisconnect));
       
  2278 	__ASSERT_DEBUG(State()==ESStateConnected || State()==ESStateShuttingDown,Panic(EBadStateUpCall));
       
  2279 
       
  2280 	iDisconnectDataError=KErrNone;
       
  2281 
       
  2282 	SetState(CanReconnect() ? ESStateCreated : ESStateDisconnected);
       
  2283 	CompleteWrite(KErrDisconnected);
       
  2284 	CompleteRead(KErrDisconnected);
       
  2285 	CompleteConnect(KErrDisconnected);
       
  2286 	TryToCompleteSelectIoctl();
       
  2287 	}
       
  2288 
       
  2289 void ASocket::Disconnect(TDesC8& aDisconnectData)
       
  2290 /**
       
  2291 Called from protocol to indicate that a disconnect has been initiated - prob from the remote host - with disconnect data
       
  2292 */
       
  2293 	{
       
  2294 	__ASSERT_DEBUG(IsConnectionOriented(),Panic(EBadDisconnect));
       
  2295 	__ASSERT_DEBUG(State()==ESStateConnected || State()==ESStateShuttingDown,Panic(EBadStateUpCall));
       
  2296 
       
  2297 	Disconnect();
       
  2298 	iDisconnectData=aDisconnectData.Alloc();
       
  2299 	if(!iDisconnectData)
       
  2300 		{
       
  2301 		iDisconnectDataError = KErrNoMemory;
       
  2302 		}
       
  2303 	else
       
  2304 		{
       
  2305 		iDisconnectDataError = KErrNone;
       
  2306 		}
       
  2307 	}
       
  2308 
       
  2309 void ASocket::DisconnectFromListener(CSubConnectionFlowBase& aSSP)
       
  2310 /**
       
  2311 Called from protocol to indicate that a disconnect has been initiated for an SAP which has not been
       
  2312 accepted yet and is waiting in the accept queue of a listening socket
       
  2313 */
       
  2314   	{
       
  2315   	#ifdef _DEBUG
       
  2316   		TBool found = EFalse;
       
  2317   	#endif
       
  2318 
       
  2319   	while(iAcceptQ->Count())
       
  2320   		{
       
  2321   		// Remove the entry from the old queue.
       
  2322   		TAcceptQEntry a;
       
  2323   		iAcceptQ->Remove(&a);
       
  2324 
       
  2325   		// Add it to the new queue if it is not the one we want to remove.
       
  2326   		if(a.iSSP != &aSSP)
       
  2327   			{
       
  2328   			iNextAcceptQ->Add(&a);
       
  2329   			}
       
  2330 #ifdef _DEBUG
       
  2331 		else
       
  2332 			{
       
  2333 			found = ETrue;
       
  2334 			}
       
  2335 #endif
       
  2336   		}
       
  2337 
       
  2338   	// Swap the queues.
       
  2339   	CCirBuf<TAcceptQEntry>* temp = iNextAcceptQ;
       
  2340   	iNextAcceptQ = iAcceptQ;
       
  2341   	iAcceptQ = temp;
       
  2342 
       
  2343   	__ASSERT_DEBUG(found,Panic(EBadDisconnectFromListener));
       
  2344   	}
       
  2345 
       
  2346 void ASocket::IoctlComplete(TDesC8 *aBuf)
       
  2347 /**
       
  2348 Called from protocol to indicate that an outstanding ioctl has completes
       
  2349 */
       
  2350 	{
       
  2351 
       
  2352 	if (aBuf && !iBlockedIoctlMsg->IsNull (MSG_PRM(1)))
       
  2353 		{
       
  2354 		TInt ret = iBlockedIoctlMsg->WriteDes(MSG_PRM(1),*aBuf);
       
  2355 		if(ret!= KErrNone)
       
  2356 			{
       
  2357 			return;
       
  2358 			}
       
  2359 		}
       
  2360 	CompleteIoctl(KErrNone);
       
  2361 	}
       
  2362 	
       
  2363 void ASocket::SetLocalNameComplete()
       
  2364 /**
       
  2365 Called from protocol to indicate that an outstanding Bind  has completed
       
  2366 */
       
  2367     {
       
  2368     if (State() == ESStateBinding)
       
  2369       	{
       
  2370       	// A SetLocalName or Autobind had just completed.
       
  2371     	SetState(iNextState); // Move to next state.
       
  2372     	iIsBound=ETrue;
       
  2373     	
       
  2374     	switch(iNextState)
       
  2375     		{
       
  2376 		case ESStateCreated:
       
  2377 		case ESStateOpen:
       
  2378 			CompleteSetLocalName(KErrNone);
       
  2379 			break;
       
  2380 		case ESStateConnected:
       
  2381 			// UDP case
       
  2382 			TryToCompleteSelectIoctl();
       
  2383 			CompleteConnect(KErrNone);
       
  2384 			break;
       
  2385 		case ESStateOpeningActive:
       
  2386 			if (CanSendConnectData() && iConnectData)
       
  2387 				{
       
  2388 		        TDes8* sendBuf = BorrowTemporaryBuffer(KMaxStreamChunk);
       
  2389 		        TInt ret;
       
  2390 		        if(!sendBuf)
       
  2391 		            {
       
  2392 		            ret = KErrNoMemory;
       
  2393 		            }
       
  2394 		        else
       
  2395 		            {
       
  2396 		            ret = GetUserMessage(ESocketConnectMessage)->ReadDes(MSG_PRM(1), *sendBuf);
       
  2397 		            }
       
  2398 				if (ret == KErrNone)
       
  2399 					{
       
  2400 					iSSP->ActiveOpen(*sendBuf);
       
  2401 					}
       
  2402 				else
       
  2403 					{
       
  2404 					CompleteConnect(ret);
       
  2405 					}
       
  2406 				}
       
  2407 			else
       
  2408 				{
       
  2409 				iSSP->ActiveOpen();
       
  2410 				}
       
  2411 			break;
       
  2412 		default:
       
  2413 			break;
       
  2414     		}
       
  2415       	}
       
  2416     }
       
  2417 
       
  2418 void ASocket::CancelConnect()
       
  2419 	{
       
  2420 	if (State()==ESStateDead)
       
  2421  		{
       
  2422  		PanicSocketClient(ESockBadHandle);
       
  2423  		return;
       
  2424  		}
       
  2425 
       
  2426 	CompleteConnect(KErrCancel);
       
  2427 	iSSP->Shutdown(MSessionControl::EImmediate);
       
  2428 
       
  2429 	if (CanReconnect())
       
  2430 		{
       
  2431 		// Reset socket state
       
  2432 		if (IsConnectionOriented())
       
  2433 			{
       
  2434 			SetState(ESStateCreated);
       
  2435 			}
       
  2436 		else
       
  2437 			{
       
  2438 			SetState(ESStateOpen);
       
  2439 			}
       
  2440 		}
       
  2441 	else
       
  2442 		{
       
  2443 		SetState(ESStateError);
       
  2444 		}
       
  2445 
       
  2446 	}
       
  2447 
       
  2448 void ASocket::CancelAccept()
       
  2449 	{
       
  2450 	CompleteConnect(KErrCancel);
       
  2451 	}
       
  2452 
       
  2453 void ASocket::CancelAll()
       
  2454 /**
       
  2455 Cancel All pending requests
       
  2456 
       
  2457 */
       
  2458 	{
       
  2459 	CancelIoctl();
       
  2460 	CompleteWrite(KErrCancel);
       
  2461 	CompleteRead(KErrCancel);
       
  2462 	if (IsBlockedConnect())
       
  2463 		{
       
  2464 		if (State()==ESStateOpeningPassive)
       
  2465 			{
       
  2466 			CancelAccept();
       
  2467 			}
       
  2468 		else
       
  2469 			{
       
  2470 			CancelConnect();
       
  2471 			}
       
  2472 		}
       
  2473     CompleteClose(KErrCancel);
       
  2474        CompleteSetLocalName(KErrCancel);
       
  2475 	}
       
  2476 
       
  2477 void ASocket::GetInfoL()
       
  2478 /**
       
  2479 Get protocol info for this socket
       
  2480 
       
  2481 */
       
  2482 	{
       
  2483 	if (State()==ESStateNull || State()==ESStateAccepting)
       
  2484 		{
       
  2485 		SetReturn(KErrNotFound);
       
  2486 		return;
       
  2487 		}
       
  2488 
       
  2489 	__ASSERT_DEBUG(iProtocolInfo, User::Panic(KSpecAssert_ESockSSocksntsck, 7));
       
  2490 	TPckg<TProtocolDesc> p(*iProtocolInfo);
       
  2491 	WriteParamL(ESocketCurrentMessage,MSG_PRM(0),p,0);
       
  2492 	}
       
  2493 
       
  2494 TInt ASocket::Error(TInt aError, TUint aOperationMask)
       
  2495 /**
       
  2496 Error up call from SSP, carries a bitmask indicating exactly which operations to signal the error on.
       
  2497 */
       
  2498 	{
       
  2499 #if defined(SYMBIAN_NETWORKING_LEGACY_COMPATIBILITY_SUPPORT)
       
  2500 	// Support for the IP stack's just-in-time resetting of a shutdown socket's state is is provided by allowing it
       
  2501 	// to notify via a pseudo-error. This is all in support of regrettable behaviour that after a shutdown TCP and UDP
       
  2502 	// sockets must complete reads & writes with a different error code to all other sockets.
       
  2503 	if(aOperationMask == MSessionControlNotify::EErrorLegacySupportRequest)
       
  2504 		{
       
  2505 		SetState((TSocketState) aError);
       
  2506 		return KErrNone;
       
  2507 		}
       
  2508 #endif
       
  2509 	if (aOperationMask == MSessionControlNotify::EErrorCompleteConnect)
       
  2510 	    {
       
  2511 	    CompleteConnect(aError);
       
  2512 	    }
       
  2513 	else
       
  2514 	    {
       
  2515     	DoError(aError, aOperationMask, ETrue);
       
  2516 	    }
       
  2517 
       
  2518 	return State() == ESStateError ? KErrGeneral : KErrNone;
       
  2519 	}
       
  2520 
       
  2521 void ASocket::DoError(TInt aError, TUint aOperationMask, TBool /*aDeleteInterface*/)
       
  2522 	{
       
  2523 	__ASSERT_DEBUG(iState!=ESStateDead,Panic(EBadStateUpCall));
       
  2524 //	__ASSERT_DEBUG(iState!=ESStateError,Panic(EBadStateUpCall));
       
  2525 	//__ASSERT_DEBUG(iState!=ESStateDisconnected,Panic(EBadStateUpCall));
       
  2526 	//__ASSERT_DEBUG(anError!=KErrNone,Panic(EBadErrorCall));
       
  2527 
       
  2528 	// completionMask remembers whether there were any pending operations that were not completed,
       
  2529 	// and whether the error is fatal (i.e. the socket permanently returns an error).
       
  2530     TUint completionMask = aOperationMask & MSessionControlNotify::EErrorFatal;
       
  2531 	if (aOperationMask & MSessionControlNotify::EErrorClose)
       
  2532 		{
       
  2533 		if (!CompleteClose(aError))
       
  2534 			{
       
  2535 			completionMask |= MSessionControlNotify::EErrorClose;
       
  2536 			}
       
  2537 		}
       
  2538 
       
  2539 	if (aOperationMask & MSessionControlNotify::EErrorRecv)
       
  2540 		{
       
  2541         if (!CompleteRead(aError))
       
  2542         	{
       
  2543 	        completionMask |= MSessionControlNotify::EErrorRecv;
       
  2544         	}
       
  2545 		}
       
  2546 
       
  2547 	if (aOperationMask & MSessionControlNotify::EErrorSend)
       
  2548 		{
       
  2549 		if (!CompleteWrite(aError))
       
  2550 			{
       
  2551 	        completionMask |= MSessionControlNotify::EErrorSend;
       
  2552 			}
       
  2553 		}
       
  2554 
       
  2555 	if ((aOperationMask&MSessionControlNotify::EErrorIoctl) && !iSelectFlags)
       
  2556 		{
       
  2557 		CompleteIoctl(aError);
       
  2558 		}
       
  2559 	if (aOperationMask & MSessionControlNotify::EErrorCompleteSetLocalName)
       
  2560 		{
       
  2561 		CompleteSetLocalName(aError);
       
  2562 		}
       
  2563 
       
  2564     iError = aError;
       
  2565     if (completionMask)
       
  2566         {
       
  2567         iErrorOperationMask = aOperationMask & completionMask;
       
  2568         }
       
  2569         
       
  2570 	if (State() == ESStateBinding && ((iNextState == ESStateCreated) || (iNextState == ESStateOpen)))
       
  2571 		{
       
  2572 		// If SetLocalName in progress then do not put the socket to
       
  2573 		// a sticky error state.
       
  2574 		iError = KErrNone;
       
  2575 		// Reset socket state.
       
  2576 		if (!IsConnectionOriented())
       
  2577 			{
       
  2578 			SetState(ESStateOpen);
       
  2579 			}
       
  2580 		else
       
  2581 			{
       
  2582 			SetState(ESStateCreated);
       
  2583 			}
       
  2584 		}
       
  2585 		else
       
  2586 
       
  2587 	if (aOperationMask & MSessionControlNotify::EErrorConnect || aOperationMask&MSessionControlNotify::EErrorFatal)
       
  2588 		{
       
  2589 		CompleteConnect(aError);
       
  2590 
       
  2591 		// KErrNoMemory not treated as a fatal error
       
  2592 		if (aError == KErrBindersInvalid || (!CanReconnect() && aError != KErrNoMemory))
       
  2593 			{
       
  2594 			// Fatal error
       
  2595 			iError = aError;
       
  2596 			SetState(ESStateError);
       
  2597 			}
       
  2598 		else
       
  2599 			{
       
  2600 			// Reset socket state
       
  2601 			if (!IsConnectionOriented())
       
  2602 				{
       
  2603 				SetState(ESStateOpen);
       
  2604 				}
       
  2605 			else
       
  2606 				{
       
  2607 				SetState(ESStateCreated);
       
  2608 				}
       
  2609 			}
       
  2610 		}
       
  2611 
       
  2612     if (iError == KErrBindersInvalid)
       
  2613         {
       
  2614         __ASSERT_DEBUG(iFlowBinder, User::Panic(KSpecAssert_ESockSSocksntsck, 8));
       
  2615         iFlowBinder->Unbind();
       
  2616       	iFlowBinder = NULL;
       
  2617        	iSSP = NULL;
       
  2618        	iSSPData = NULL;
       
  2619        	iServiceProvider.Close();
       
  2620         }
       
  2621 	TryToCompleteSelectIoctl();
       
  2622 	}
       
  2623 
       
  2624 TInt ASocket::DrainStreamProtocol(AMessage* aMsg)
       
  2625 /**
       
  2626  Drain a stream based protocol into client buffers.
       
  2627 */
       
  2628 	{
       
  2629 	__ASSERT_DEBUG(iDataAvailable>=0,Panic(EBadByteCount));
       
  2630 	__ASSERT_DEBUG(iRecByteCount>=0,Panic(EBadByteCount));
       
  2631 
       
  2632 	TDes8* recBuf = NULL;
       
  2633 	if(!iRecvUseMBufs)
       
  2634 		{
       
  2635 		TInt xferBufSize = Min((TInt) KMaxStreamChunk, Min(iDataAvailable, iRecByteCount));
       
  2636 		recBuf = BorrowTemporaryBuffer(xferBufSize);
       
  2637 		if(!recBuf)
       
  2638 			{
       
  2639 			return KErrNoMemory;
       
  2640 			}
       
  2641 		}
       
  2642 
       
  2643 #ifdef SYMBIAN_NETWORKING_PERFMETRICS
       
  2644 	TInt rxActual = 0;
       
  2645 #endif
       
  2646 
       
  2647 	RMBufChain data;
       
  2648 	TInt ret = KErrNone;
       
  2649 	do
       
  2650 		{
       
  2651         TInt xfrLen;
       
  2652         if (iRecvUseMBufs)
       
  2653 			{
       
  2654 			// We are using RMBufChain.	So we can read the complete data that is available
       
  2655 			xfrLen = iDataAvailable;
       
  2656 			}
       
  2657 	     else
       
  2658 			{
       
  2659 			xfrLen = Min(recBuf->MaxLength(), Min(iDataAvailable, iRecByteCount));
       
  2660 			}
       
  2661 
       
  2662 		if (xfrLen==0)
       
  2663 			{
       
  2664 			return KErrNone;
       
  2665 			}
       
  2666 
       
  2667 
       
  2668 		RMBufChain data;
       
  2669 		ret = iSSPData->GetData(data, xfrLen, iRecvFlags);
       
  2670 		if (ret == 0 && iBlockedOperations&EReadStopped)
       
  2671 			{
       
  2672 			/* Look for the special case, where the SSP renegs on the amount of
       
  2673 			 * data available after an EStopInput Shutdown, as that can stop us
       
  2674 			 * ever exiting this while loop. */
       
  2675 			iDataAvailable = 0;
       
  2676 			return KErrEof;
       
  2677 			}
       
  2678 		if(ret >= 0)
       
  2679 			{
       
  2680 			// Now we received something.
       
  2681 			if (iRecvUseMBufs)
       
  2682 				{
       
  2683 				ret = aMsg->WriteMBuf(MSG_PRM(2), data );
       
  2684 				// No need to delete as the write operation has taken the ownership of our RMBufChain
       
  2685 				}
       
  2686 			else
       
  2687 				{
       
  2688 				// Default assumption is multi-buf chain
       
  2689 				TPtr8 des(const_cast<TUint8*>(recBuf->Ptr()), xfrLen, xfrLen);
       
  2690 				if(!data.First()->Next())
       
  2691 					{
       
  2692 					// Actually data is all in one buf; repoint descriptor at that
       
  2693 					des.Set(data.First()->Ptr(), data.First()->Length(), data.First()->Length()); 
       
  2694 					}
       
  2695 				else
       
  2696 					{
       
  2697 					data.CopyOut(des, 0);
       
  2698 					}
       
  2699 				xfrLen = des.Length();
       
  2700             	ret = aMsg->WriteDes(MSG_PRM(2), des, iRecOffset);
       
  2701 				if ( ret == KErrNone )
       
  2702 					{
       
  2703 					data.Free(); // Free the chain
       
  2704 					}
       
  2705 				}
       
  2706             if(ret == KErrNone)
       
  2707 				{
       
  2708 #ifdef SYMBIAN_NETWORKING_PERFMETRICS
       
  2709 				rxActual += ipcLen;
       
  2710 #endif
       
  2711 				iRecOffset += xfrLen;
       
  2712                 iDataAvailable -= xfrLen;
       
  2713 				iRecByteCount -= xfrLen;
       
  2714 				}
       
  2715 			}
       
  2716 		else if(xfrLen <= 0)
       
  2717 			{
       
  2718 			// Failed to read or write on this iteration; we're done
       
  2719 			break;
       
  2720 			}
       
  2721 		} while(ret == KErrNone);
       
  2722 
       
  2723 #ifdef SYMBIAN_NETWORKING_PERFMETRICS
       
  2724 	IncludePerformanceData(rxActual, -1, -1);
       
  2725 #endif
       
  2726 	return ret;
       
  2727 	}
       
  2728 
       
  2729 TInt ASocket::FillStreamProtocol(AMessage* aMsg)
       
  2730 /**
       
  2731  Fill a stream protocol from client buffers
       
  2732 */
       
  2733 	{
       
  2734 	__ASSERT_DEBUG(iSendByteCount>=0,Panic(EBadByteCount));
       
  2735 	TPtr8 des(NULL, 0);
       
  2736 	TDes8* sendBuf;
       
  2737 	if(!iSendUseMBufs)
       
  2738 		{
       
  2739 		sendBuf = BorrowTemporaryBuffer(Min((TInt) KMaxStreamChunk, iSendByteCount));
       
  2740 		if(!sendBuf)
       
  2741 			{
       
  2742 			return KErrNoMemory;
       
  2743 			}
       
  2744 		}
       
  2745 	else
       
  2746 		{
       
  2747 		sendBuf = NULL;
       
  2748 		}
       
  2749 
       
  2750 	RMBufChain data;
       
  2751 	data.Assign(iSendData);	// pick up any flowed-off chain
       
  2752 	TInt xfrLen = data.Length();
       
  2753 
       
  2754 	do
       
  2755 		{
       
  2756 		TInt err = KErrNone;
       
  2757 		if(data.IsEmpty())
       
  2758 			{
       
  2759 			// Need to pick up more data from client
       
  2760 			if (!iSendUseMBufs)
       
  2761 				{
       
  2762 				xfrLen = Min(sendBuf->Size(), iSendByteCount);
       
  2763 				err = data.Alloc(xfrLen, iAllocator);
       
  2764 				if(err == KErrNone)
       
  2765 					{
       
  2766 					RMBuf* first = data.First();
       
  2767 					if(first->Length() >= xfrLen)
       
  2768 						{
       
  2769 						des.Set(first->Ptr(), xfrLen, xfrLen);
       
  2770 						err = aMsg->ReadDes(MSG_PRM(2),des, iSendOffset);
       
  2771 						}
       
  2772 					else
       
  2773 						{
       
  2774 						des.Set(const_cast<TUint8*>(sendBuf->Ptr()), xfrLen, xfrLen);
       
  2775 						err = aMsg->ReadDes(MSG_PRM(2), des, iSendOffset);
       
  2776 						data.CopyIn(des);	// read failure exceedingly rare so don't bother checking return yet
       
  2777 						}
       
  2778 					if(err != KErrNone)
       
  2779 						{
       
  2780 						data.Free();
       
  2781 						}
       
  2782 					}
       
  2783 				}
       
  2784 			else
       
  2785 				{
       
  2786 				err = aMsg->ReadMBuf(MSG_PRM(2), data);
       
  2787 				if(err == KErrNone)
       
  2788 					{
       
  2789 					xfrLen = data.Length();
       
  2790 					}
       
  2791 				}
       
  2792 			}
       
  2793 		else
       
  2794 		    {
       
  2795 		    xfrLen = data.Length();
       
  2796 		    }
       
  2797 		if(err != KErrNone)
       
  2798 			{
       
  2799 			// Failed getting data from the client; bail now without further disturbing the state
       
  2800 			return err;
       
  2801 			}
       
  2802 		
       
  2803 		err = iSSPData->Write(data, iSendFlags, NULL);
       
  2804 		
       
  2805 		// If a protocol takes only part of the chain they must update it so that we have the new head
       
  2806 		__ASSERT_DEBUG(err <= 0 || err == (xfrLen - data.Length()), Panic(EBadByteCount));  
       
  2807 		
       
  2808 		if(err <= 0)	// protocol error or flow-off
       
  2809 			{
       
  2810 			if(err == 0)
       
  2811 			    {
       
  2812                 iSendData.Assign(data);	// keep the MBuf chain for flow-on. In future we could be cleverer and later free this when MBufs are running low
       
  2813                 iBlockedOperations|=EWriteFlowedOff;
       
  2814 			    }
       
  2815 			else 
       
  2816 			    {
       
  2817 			    data.Free();
       
  2818 			    }
       
  2819 			return err;
       
  2820 			}
       
  2821 		iSendOffset += err;
       
  2822 		iSendByteCount -= err;
       
  2823 		} while(iSendByteCount > 0);
       
  2824 
       
  2825 	// We successfully completed.
       
  2826 	if ( iSendUseMBufs )
       
  2827 		{
       
  2828 		// Protection against possible non-deletion by SAP
       
  2829 		data.Free ();
       
  2830 		// We have to init the RMBufChain, so that caller see that everything send
       
  2831 		aMsg->InitMBuf(MSG_PRM(2));
       
  2832 		}
       
  2833 	return KErrNone;
       
  2834 	}
       
  2835 
       
  2836 TBool ASocket::CheckRunningAndSetReturn()
       
  2837 /**
       
  2838 Check a common set of states and set the return value is required.
       
  2839 */
       
  2840 {
       
  2841 	switch(State())
       
  2842 		{
       
  2843 	case ESStateNull:
       
  2844 	case ESStateAccepting:
       
  2845 		PanicSocketClient(ENullSocket);
       
  2846 		//lint -fallthrough
       
  2847 	case ESStateDead:
       
  2848 	case ESStateClosing:
       
  2849 		SetReturn(KErrBadHandle);
       
  2850 		return EFalse;
       
  2851 	case ESStateDisconnected:
       
  2852 		SetReturn(KErrDisconnected);
       
  2853 		return EFalse;
       
  2854 	case ESStateError:
       
  2855 		SetReturn(iError);
       
  2856 		return EFalse;
       
  2857 	default:
       
  2858 		return ETrue;
       
  2859 		}
       
  2860 	}
       
  2861 
       
  2862 /**
       
  2863 Complete any outstanding read operation.
       
  2864 @param aError error code with which to complete the pending operation
       
  2865 @return ETrue if a pending operation was completed, else EFalse.
       
  2866 */
       
  2867 TBool ASocket::CompleteRead(TInt aError)
       
  2868 	{
       
  2869 	if (IsBlockedRead())
       
  2870 		{
       
  2871 		if(iAllocAsync)
       
  2872 			{
       
  2873 			iAllocAsync->CancelNewData();
       
  2874 			}
       
  2875 		iBlockedOperations&=~EBlockedRead;
       
  2876 		iReadMsg->CompleteMessage(aError);
       
  2877         return ETrue;
       
  2878         }
       
  2879     else
       
  2880         {
       
  2881         return EFalse;
       
  2882    		}
       
  2883 	}
       
  2884 
       
  2885 /**
       
  2886 Complete any outstanding write operation.
       
  2887 @param aError error code with which to complete the pending operation
       
  2888 @return ETrue if a pending operation was completed, else EFalse.
       
  2889 */
       
  2890 TBool ASocket::CompleteWrite(TInt aError)
       
  2891 	{
       
  2892 	if (IsBlockedWrite())
       
  2893 		{
       
  2894 		if(iAllocAsync)
       
  2895 			{
       
  2896 			iAllocAsync->CancelCanSend();
       
  2897 			}
       
  2898 		iBlockedOperations&=~EBlockedWrite;
       
  2899 		iWriteMsg->CompleteMessage(aError);
       
  2900 		iSendData.Free();
       
  2901 		return ETrue;
       
  2902 		}
       
  2903 	else
       
  2904 		{
       
  2905 		return EFalse;
       
  2906 		}
       
  2907 	}
       
  2908 
       
  2909 void ASocket::CompleteConnect(TInt aError)
       
  2910 	{
       
  2911 	if (IsBlockedConnect())
       
  2912 		{
       
  2913 		iBlockedOperations&=~EBlockedConnect;
       
  2914 		iBlockedConnectMsg->CompleteMessage(aError);
       
  2915 		}
       
  2916 	}
       
  2917 
       
  2918 TBool ASocket::CompleteClose(TInt aError)
       
  2919 	{
       
  2920 	if (IsBlockedClose())
       
  2921 		{
       
  2922 		iBlockedOperations&=~EBlockedClose;
       
  2923 		iBlockedCloseMsg->CompleteMessage(aError);
       
  2924 		return ETrue;
       
  2925 		}
       
  2926 	return EFalse;
       
  2927 	}
       
  2928 
       
  2929 
       
  2930 void ASocket::CompleteIoctl(TInt aError)
       
  2931 	{
       
  2932 	if (IsBlockedIoctl())
       
  2933 		{
       
  2934 		iBlockedOperations&=~EBlockedIoctl;
       
  2935 		iBlockedIoctlMsg->CompleteMessage(aError);
       
  2936 //		LOG(ESockLog::Printf(KESockSessDetailTag, _L8("ASocket::CompleteIoctl completing %08x "), iBlockedIoctl.Handle()) );
       
  2937 		}
       
  2938 	}
       
  2939 	
       
  2940 void ASocket::CompleteSetLocalName( TInt aError )
       
  2941     {
       
  2942     if (IsBlockedSetLocalName())
       
  2943 		{
       
  2944 		// SetLocalName has completed.
       
  2945 		iBlockedOperations &= ~EBlockedSetLocalName;
       
  2946 		iBlockedSetLocalNameMsg->CompleteMessage(aError);
       
  2947 		}
       
  2948     }	
       
  2949 
       
  2950 TUint ASocket::SelectConditionsReady()
       
  2951 /**
       
  2952 Which select conditions are ready
       
  2953 */
       
  2954     {
       
  2955 
       
  2956 	TUint flags=0;
       
  2957 	// Exceptional condition
       
  2958 	if(iError!=KErrNone)
       
  2959 		{
       
  2960 		flags|=KSockSelectExcept;
       
  2961 		}
       
  2962 
       
  2963 	// Ready to read - either data or an accept is ready
       
  2964 	if(iDataAvailable
       
  2965 			|| ((iSelectFlags & KSockReadContinuation) != 0 && !iDatagramTail.IsEmpty())
       
  2966 			|| (State()==ESStateOpeningPassive && iAcceptQ->Count())
       
  2967 		    || (iBlockedOperations&EReadStopped))
       
  2968 		{
       
  2969 		flags|=KSockSelectRead;
       
  2970 		}
       
  2971 
       
  2972 	// Ready to write - must be connected and cannot be blocking
       
  2973 	if((State()==ESStateConnected || State()==ESStateOpen || State()==ESStateShuttingDown)
       
  2974 		&& !(iBlockedOperations&EWriteFlowedOff) )
       
  2975 		{
       
  2976 		flags|=KSockSelectWrite;
       
  2977 		}
       
  2978 
       
  2979 	return flags;
       
  2980     }
       
  2981 
       
  2982 void ASocket::TryToCompleteSelectIoctl()
       
  2983 /**
       
  2984 have a go at completing the select ioctl
       
  2985 */
       
  2986     {
       
  2987 
       
  2988 	if(iSelectFlags)
       
  2989 	   {
       
  2990 	   TUint ready = (iSelectFlags & SelectConditionsReady());
       
  2991 	   if(ready)
       
  2992 	       {
       
  2993 	       TPckg<TUint> buf(ready);
       
  2994            IoctlComplete(&buf);
       
  2995 	       iSelectFlags=0;
       
  2996 	       }
       
  2997 	   }
       
  2998     }
       
  2999 
       
  3000 TBool ASocket::CheckReadStopped()
       
  3001 /**
       
  3002 Has reading stopped
       
  3003 */
       
  3004 	{
       
  3005 	if((iBlockedOperations&EReadStopped) && iDataAvailable<=0)
       
  3006 		{
       
  3007 		TPtrC8 ptr(0,0);
       
  3008 		TInt ret = iReadMsg->WriteDes(MSG_PRM(2), ptr);
       
  3009 		if(iRecvXferLenIdx >= 0)
       
  3010 			{
       
  3011 			iXferLength() = 0;
       
  3012 			ret = iReadMsg->WriteDes(iRecvXferLenIdx, iXferLength);
       
  3013 			if(ret!= KErrNone)
       
  3014 				{
       
  3015 				return EFalse;
       
  3016 				}
       
  3017 			}
       
  3018 		return ETrue;
       
  3019 		}
       
  3020 	return EFalse;
       
  3021 	}
       
  3022 
       
  3023 void ASocket::CommunicateOwner()
       
  3024 /**
       
  3025 Communicate Thread ID, Process ID and UID to SAP.
       
  3026 
       
  3027 */
       
  3028 	{
       
  3029 	if (RequiresOwnerInfo())
       
  3030 		{
       
  3031 
       
  3032 		TSoOwnerInfo info;
       
  3033 
       
  3034 		// Not using more Networking specific macro SYMBIAN_NETWORKING_UPS because this support
       
  3035 		// is required by UPS functionality outside of Networking subsystem as well.
       
  3036 		GetOwnerInfo(info.iProcessId, info, info.iThreadId);
       
  3037 
       
  3038 		iSSP->SetOption(KSOLProvider, KSoOwnerInfo, TPckgC<TSoOwnerInfo>(info));
       
  3039 
       
  3040 #ifdef SYMBIAN_NETWORKING_UPS
       
  3041 		iSSP->SetOption(KSOLProvider, KSoSetPlatSecApi, TPckgC<const MPlatsecApiExt*>(this));
       
  3042 #endif
       
  3043 		}
       
  3044 	}
       
  3045 
       
  3046 TInt ASocket::GetConnectionSocketInfo(TConnectionSocketInfo& aInfo) const
       
  3047 /**
       
  3048 Return information about this socket
       
  3049 */
       
  3050 	{
       
  3051 	__ASSERT_DEBUG(iSSP, User::Panic(KSpecAssert_ESockSSocksntsck, 10));
       
  3052 
       
  3053 	if(iIsBound)
       
  3054 		{
       
  3055 		iSSP->LocalName(aInfo.iSourceAddress);
       
  3056 		}
       
  3057 	else
       
  3058 		{
       
  3059 		return KErrNotFound;
       
  3060 		}
       
  3061 
       
  3062 	if (State()==ESStateConnected || State()==ESStateOpeningActive || State()==ESStateShuttingDown)
       
  3063 		{
       
  3064 		iSSP->RemName(aInfo.iDestinationAddress);
       
  3065 		}
       
  3066 	else
       
  3067 		{
       
  3068 		return KErrNotFound;
       
  3069 		}
       
  3070 
       
  3071 	__ASSERT_DEBUG(iProtocolInfo, User::Panic(KSpecAssert_ESockSSocksntsck, 11));
       
  3072 
       
  3073 	aInfo.iAddressFamily = iProtocolInfo->iAddrFamily;
       
  3074 	aInfo.iProtocol = iProtocolInfo->iProtocol;
       
  3075 
       
  3076 	return KErrNone;
       
  3077 	}
       
  3078 
       
  3079 TInt ASocket::RequestAsyncMBufAllocation(TInt aSignal, TUint aSize)
       
  3080 	{
       
  3081 	TInt ret = KErrNone;
       
  3082 	if(!iAllocAsync)
       
  3083 		{
       
  3084 		TRAP(ret, iAllocAsync = CWaitForMBufs::NewL(this));
       
  3085 		if(ret != KErrNone)
       
  3086 			{
       
  3087 			// This second-chance mechanism has failed; it's now reasonable just to error the client
       
  3088 			Error(KErrNoMemory, aSignal == CWaitForMBufs::ECanSend? MSessionControlNotify::EErrorSend: MSessionControlNotify::EErrorRecv);
       
  3089 			}
       
  3090 		}
       
  3091 
       
  3092 	if(aSignal == CWaitForMBufs::ENewData)
       
  3093 		{
       
  3094 		iAllocAsync->AllocWaitAndSignalNewData(aSize);
       
  3095 		}
       
  3096 	else
       
  3097 		{
       
  3098 		if(aSignal == CWaitForMBufs::ECanSend)
       
  3099 			{
       
  3100 			iAllocAsync->AllocWaitAndSignalCanSend(aSize);
       
  3101 			}
       
  3102 		}
       
  3103 
       
  3104 	return ret;
       
  3105 	}
       
  3106 
       
  3107 void ASocket::ReadParamL(TSocketMessage aMessage, TInt aSrcParamIndex,TDes8 &aDes,TInt anOffset)
       
  3108 	{
       
  3109 	User::LeaveIfError(GetUserMessage(aMessage)->ReadDes(aSrcParamIndex, aDes, anOffset));
       
  3110 	}
       
  3111 
       
  3112 void ASocket::ReadParamL(TSocketMessage aMessage, TInt aSrcParamIndex, RMBufChain& aBufChain)
       
  3113 	{
       
  3114 	User::LeaveIfError(GetUserMessage(aMessage)->ReadMBuf(aSrcParamIndex, aBufChain));
       
  3115 	}
       
  3116 
       
  3117 void ASocket::WriteParamL(TSocketMessage aMessage, TInt aDstParamIndex,const TDesC8& aDes,TInt anOffset)
       
  3118 	{
       
  3119 	User::LeaveIfError(GetUserMessage(aMessage)->WriteDes(aDstParamIndex, aDes, anOffset));
       
  3120 	}
       
  3121 
       
  3122 void ASocket::WriteParamL(TSocketMessage aMessage, TInt aDstParamIndex, RMBufChain& aBufChain)
       
  3123 	{
       
  3124 	User::LeaveIfError(GetUserMessage(aMessage)->WriteMBuf(aDstParamIndex, aBufChain));
       
  3125 	}
       
  3126 
       
  3127 AMessage* ASocket::GetUserMessage( TSocketMessage aMessage ) const
       
  3128 	{
       
  3129 	AMessage* msg = NULL;
       
  3130 	switch (aMessage)
       
  3131 		{
       
  3132 			case ESocketCurrentMessage:
       
  3133 			msg = iCurrentMsg;
       
  3134 			break;
       
  3135 
       
  3136 			case ESocketReadMessage:
       
  3137 			msg = iReadMsg;
       
  3138 			break;
       
  3139 
       
  3140 			case ESocketWriteMessage:
       
  3141 			msg = iWriteMsg;
       
  3142 			break;
       
  3143 
       
  3144 			case ESocketCloseMessage:
       
  3145 			msg = iBlockedCloseMsg;
       
  3146 			break;
       
  3147 
       
  3148 			case ESocketIoCtlMessage:
       
  3149 			msg = iBlockedIoctlMsg;
       
  3150 			break;
       
  3151 
       
  3152 			case ESocketConnectMessage:
       
  3153 			msg = iBlockedConnectMsg;
       
  3154 			break;
       
  3155 			case ESocketSetLocalNameMessage:
       
  3156 			msg = iBlockedSetLocalNameMsg;
       
  3157 			break;
       
  3158 
       
  3159 			default:
       
  3160 			__ASSERT_DEBUG(0, User::Panic(KSpecAssert_ESockSSocksntsck, 12));
       
  3161 		}
       
  3162 	return msg;
       
  3163 	}
       
  3164 
       
  3165 void ASocket::SetUserMessage ( TSocketMessage aMessageType, AMessage* aMessage )
       
  3166 	{
       
  3167 	switch (aMessageType)
       
  3168 		{
       
  3169 			case ESocketCurrentMessage:
       
  3170 			iCurrentMsg = aMessage;
       
  3171 			break;
       
  3172 
       
  3173 			case ESocketReadMessage:
       
  3174 			iReadMsg = aMessage;
       
  3175 			break;
       
  3176 
       
  3177 			case ESocketWriteMessage:
       
  3178 			iWriteMsg = aMessage;
       
  3179 			break;
       
  3180 
       
  3181 			case ESocketCloseMessage:
       
  3182 			iBlockedCloseMsg = aMessage;
       
  3183 			break;
       
  3184 
       
  3185 			case ESocketIoCtlMessage:
       
  3186 			iBlockedIoctlMsg = aMessage;
       
  3187 			break;
       
  3188 
       
  3189 			case ESocketConnectMessage:
       
  3190 			iBlockedConnectMsg = aMessage;
       
  3191 			break;
       
  3192 			case ESocketSetLocalNameMessage:
       
  3193 			iBlockedSetLocalNameMsg = aMessage;
       
  3194 			break;
       
  3195 
       
  3196 			default:
       
  3197 			__ASSERT_DEBUG(0, User::Panic(KSpecAssert_ESockSSocksntsck, 13));
       
  3198 		}
       
  3199 	}
       
  3200 
       
  3201 
       
  3202 #ifdef SYMBIAN_NETWORKING_UPS
       
  3203 TInt ASocket::GetProcessAndThreadId(TProcessId& aProcessId, TThreadId& aThreadId) const
       
  3204 /**
       
  3205 Retrieve the process and thread id associated with the pending request.
       
  3206 */
       
  3207 	{
       
  3208 	TSocketMessage msg = ESocketCurrentMessage;
       
  3209 
       
  3210 	if (IsBlockedConnect())
       
  3211 		{
       
  3212 		msg = ESocketConnectMessage;
       
  3213 		}
       
  3214 	else
       
  3215 	if (IsBlockedWrite())
       
  3216 		{
       
  3217 		msg = ESocketWriteMessage;
       
  3218 		}
       
  3219 	if (msg != ESocketCurrentMessage || (iState == ESStateCreated || iState == ESStateOpen))
       
  3220 		{
       
  3221 		// Guard against an invalid current message - especially for a Connect/CancelConnect scenario
       
  3222 		// whereby the socket is in the ESStateError state.  Needs revisiting.
       
  3223 		return GetUserMessage(msg)->GetProcessAndThreadId(aProcessId, aThreadId);
       
  3224 		}
       
  3225 	else
       
  3226 		{
       
  3227 		return KErrUnknown;
       
  3228 		}
       
  3229 	}
       
  3230 
       
  3231 TInt AMessage::GetProcessAndThreadId(TProcessId& /*aProcessId*/, TThreadId& /*aThreadId*/) const
       
  3232 	{
       
  3233 	return KErrNotSupported;
       
  3234 	}
       
  3235 
       
  3236 #endif
       
  3237