datacommsserver/esockserver/test/TS_MultiHoming/CEchoSocket.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2002-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 // @file CEchoSocket.cpp
       
    15 // This contains the CEchoSocket class implementation and its saftey timer, CSafety 
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include "CEchoSocket.h"
       
    24 
       
    25 CEchoSocket::CEchoSocket() : CActive(EPriorityNormal),
       
    26 							iSockErr(KErrNone),
       
    27 							iPacketSize(CTS_MultiHomingStep::PACKET_SIZE), 
       
    28 							iPacketsToSend(CTS_MultiHomingStep::NUM_OF_PACKETS),
       
    29 							iRecvdGood(0), 
       
    30 							iProtocol(KProtocolInetUdp), 
       
    31 							iUDPTolerance(CTS_MultiHomingStep::UDP_TOLERANCE),
       
    32 							iPtrRecvd(0,0),
       
    33 							iPtrRecvdThisRead(0,0),
       
    34 							iPtrWritn(0,0),
       
    35 							iConsecRecvTimeOuts(0),
       
    36 							iIsListener(EFalse)
       
    37 	{
       
    38 	}
       
    39 
       
    40 CEchoSocket::~CEchoSocket()
       
    41 	{
       
    42 	Cancel();
       
    43 	delete iWritebuf;
       
    44 	delete iReadbufThisRead;
       
    45 	delete iReadbuf;
       
    46 	delete iSafety;
       
    47 
       
    48 	}
       
    49 
       
    50 CEchoSocket* CEchoSocket::NewL()
       
    51 	{
       
    52 	
       
    53 	CEchoSocket* self = new(ELeave) CEchoSocket;
       
    54 	CleanupStack::PushL(self);
       
    55 	self->ConstructL();
       
    56 	CleanupStack::Pop();
       
    57 	CEnhancedScheduler::Add(self);
       
    58 	return self;
       
    59 	}
       
    60 
       
    61 
       
    62 void CEchoSocket::ConstructL()
       
    63 	{
       
    64 	iSafety = CSafety::NewL(this);
       
    65 
       
    66 	iWritebuf = HBufC8::NewMaxL(CTS_MultiHomingStep::MAX_PACKET_SIZE);
       
    67 	iPtrWritn.Set(iWritebuf->Des());
       
    68 	iReadbuf = HBufC8::NewMaxL(CTS_MultiHomingStep::MAX_PACKET_SIZE);
       
    69 	iPtrRecvd.Set(iReadbuf->Des());
       
    70 	iReadbufThisRead = HBufC8::NewMaxL(CTS_MultiHomingStep::MAX_PACKET_SIZE);
       
    71 	iPtrRecvdThisRead.Set(iReadbufThisRead->Des());
       
    72 	}
       
    73 
       
    74 void CEchoSocket::RunL()
       
    75 	{
       
    76 	
       
    77 	switch (iState)
       
    78 		{
       
    79 		case EInitialised:
       
    80 			if(iIsListener)
       
    81 				{
       
    82 				iAcceptedConnection.Open( (iTConnection->iSocketServ));
       
    83 		
       
    84 				iSocket.Accept(iAcceptedConnection, iStatus);
       
    85 				iState = EReady;
       
    86 				SetActive();
       
    87 				}
       
    88 			else 
       
    89 				{
       
    90 				if (KProtocolInetTcp == iProtocol)
       
    91 					{
       
    92 					ConnectTcp();
       
    93 					iOwnerStep->StepLog(_L("Connecting TCP %S:%i"),&iName, iSockNum);
       
    94 					}
       
    95 				else if (KProtocolInetUdp == iProtocol)
       
    96 					{
       
    97 					BindUdp();
       
    98 					iOwnerStep->StepLog(_L("Binding UDP %S:%i"), &iName, iSockNum);
       
    99 					}
       
   100 				}
       
   101 			break;	
       
   102 			
       
   103 		case EReady:
       
   104 			iSafety->Cancel();
       
   105 
       
   106 			if (iStatus == KErrNone)
       
   107 				{
       
   108 				if(iIsListener)
       
   109 					{
       
   110 					RecvDataTcpListen();
       
   111 					}
       
   112 				else
       
   113 					{
       
   114 					SendData();
       
   115 					}
       
   116 				}
       
   117 			else
       
   118 				{
       
   119 				iOwnerStep->StepLog(KErrConnectFailed,&iName,iSockNum, iStatus.Int());
       
   120 				SetComplete();
       
   121 				}
       
   122 			break;
       
   123 			
       
   124 		case ESentData:
       
   125 			if (iStatus == KErrNone)
       
   126 				{
       
   127 					if(iIsListener)
       
   128 					{
       
   129 					RecvDataTcpListen();
       
   130 					}
       
   131 				else
       
   132 					{
       
   133 					RecvData();
       
   134 					}
       
   135 				}
       
   136 			else
       
   137 				{
       
   138 				iOwnerStep->StepLog(KErrSendFailed, &iName, iSockNum, iStatus.Int());
       
   139 				SetComplete();	// Couldn't send, so bit of a problem...
       
   140 				}
       
   141 			break;
       
   142 		
       
   143 		case ERecvdData:
       
   144 			iSafety->Cancel();
       
   145 			if(iIsListener && iStatus == KErrEof)
       
   146 				{
       
   147 				SetComplete();
       
   148 				}
       
   149 			else if(iStatus == KErrNone)
       
   150 				{
       
   151 				TInt err = KErrNone;
       
   152 				// Reset our consecutive count
       
   153 				iConsecRecvTimeOuts = 0;
       
   154 				// Compare sent and received
       
   155 				err = iPtrWritn.Compare(iPtrRecvd);
       
   156  				if (err == KErrNone || iIsListener)
       
   157 					{
       
   158 					iRecvdGood++;
       
   159 					if (iPacketsToSend>0)
       
   160 						if(iIsListener)
       
   161 							SendDataToClient();						
       
   162 						else 
       
   163 							SendData();	
       
   164 					else
       
   165 						SetComplete();
       
   166 					}
       
   167 				else
       
   168 					{
       
   169 					// Try reading again, usualy happens because of a timeout
       
   170 					iOwnerStep->StepLog(KErrPacketsDiff, &iName, iSockNum);
       
   171 					RecvData();
       
   172 					}				
       
   173 				}
       
   174 			else if (KErrCancel == iStatus.Int()) // We cancelled our receive
       
   175 				{
       
   176 				iConsecRecvTimeOuts++;
       
   177 				iOwnerStep->StepLog(_L("Receive timeout on %S:%i,%d"),&iName, iSockNum,
       
   178 					iConsecRecvTimeOuts);
       
   179 				
       
   180 				if (iPacketsToSend > 0 && iConsecRecvTimeOuts < MAX_CONSEC_TIMEOUT)
       
   181 					SendData();
       
   182 				else
       
   183 					SetComplete();
       
   184 				}
       
   185 			else
       
   186 				{
       
   187 				TPtrC errorText = CLog::EpocErrorToText(iStatus.Int());
       
   188 				iOwnerStep->StepLog(KErrRecvFailed, &iName, iSockNum, &errorText);
       
   189 				SetComplete();
       
   190 				}
       
   191 			break;
       
   192 
       
   193 			
       
   194 		case EComplete:
       
   195 			iOwnerStep->iOwnerSuite->iScheduler->DecCount();
       
   196 			if(0 == iOwnerStep->iOwnerSuite->iScheduler->GetCount())
       
   197 				CEnhancedScheduler::Stop();
       
   198 			break;
       
   199 
       
   200 		default:
       
   201 			iOwnerStep->StepLog(KTxtWhatHappened);
       
   202 			break;
       
   203 		
       
   204 		}
       
   205 	// Error handling of iStatus...
       
   206 
       
   207 
       
   208 	}
       
   209 
       
   210 
       
   211 
       
   212 
       
   213 void CEchoSocket::DoCancel()
       
   214 	{
       
   215 	iSocket.CancelAll();
       
   216 	// Close is handles in set complete
       
   217 	//iSocket.Close();		
       
   218 	}
       
   219 
       
   220 TInt CEchoSocket::Echo(const TInetAddr& aDest, const TInetAddr& aSrc,
       
   221 						const TInt& aSize,	const TInt& aPackets, 
       
   222 						const TUint& aProto, const TInt& aTol,
       
   223 						TConnDetails* aConn, const TInt& aSockNum, 
       
   224 						const TBool aIsListener, CTS_MultiHomingStep* aStep)
       
   225 /**
       
   226  * Creates an Echo socket and runs it to completion or error
       
   227  * @param aSockServ The socket server to attach to
       
   228  * @param aDest The destination IP address
       
   229  * @param aSize The packet size to use in bytes
       
   230  * @param aPackets The number of packets to send
       
   231  * @param aProto The protocol to use
       
   232  * @param aTol The UDP data tolerance level
       
   233  * @return Error value for initialisation stage
       
   234  */
       
   235 	{
       
   236 	__ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCEchoSocket,KErrAlreadyExists));
       
   237 	__ASSERT_ALWAYS(aSize <= CTS_MultiHomingStep::MAX_PACKET_SIZE, User::Panic(KTxtCEchoSocket,KErrOverflow));
       
   238 	
       
   239 	// Remember the config
       
   240 	iDestAddr = aDest;
       
   241 	iSrcAddr = aSrc;
       
   242 	iPacketSize = aSize;
       
   243 	iPacketsToSend = aPackets;
       
   244 	iPackets = aPackets;
       
   245 	iProtocol = aProto;
       
   246 	iUDPTolerance = aTol;
       
   247 	iOwnerStep = aStep;
       
   248 	iTConnection = aConn;
       
   249 	iSockNum = aSockNum;
       
   250 
       
   251 	iIsListener = aIsListener;
       
   252 
       
   253 	TInt err = KErrNone;
       
   254 
       
   255 	iPtrWritn.SetLength(aSize);
       
   256 	iPtrRecvd.SetLength(aSize);
       
   257 
       
   258 	
       
   259 	if(iTConnection == 0)
       
   260 		return KErrGeneral;
       
   261 	// Open the socket for implicit or explicit case
       
   262 	if(iTConnection->iConnectionType != TConnDetails::implicitConn)
       
   263 		{
       
   264 		err = iSocket.Open( (iTConnection->iSocketServ), KAfInet, 
       
   265 					iProtocol == KProtocolInetTcp ? KSockStream : KSockDatagram, iProtocol,
       
   266 					(iTConnection->iConnection));
       
   267 		}
       
   268 	else
       
   269 		{
       
   270 		err = iSocket.Open( (iTConnection->iSocketServ), KAfInet, 
       
   271 					iProtocol == KProtocolInetTcp ? KSockStream : KSockDatagram, iProtocol);
       
   272 		}
       
   273 	if (err != KErrNone)
       
   274 		return err;			// No point going any further...
       
   275 
       
   276 	iSocket.Name(iName);
       
   277 	
       
   278 	err = iSocket.SetOpt(KSolInetIp, KSoReuseAddr, 1);
       
   279 	// Ignore this error for unbound sockets
       
   280 	err = iSocket.Bind(iSrcAddr);
       
   281 	if(err != KErrNone)
       
   282 		return err;
       
   283 
       
   284 	if(iProtocol == KProtocolInetTcp)
       
   285 		{
       
   286 		// Disable the nagle algorithm.
       
   287 		iSocket.SetOpt(KSoTcpNoDelay, KSolInetTcp, 1);
       
   288 		}
       
   289 	if(iIsListener)
       
   290 		{
       
   291 		// Accept a single connection
       
   292 		iSocket.Listen(1);
       
   293 		}
       
   294 
       
   295 	iState = EInitialised;
       
   296 
       
   297 	iStatus = KRequestPending;
       
   298 	SetActive();
       
   299 
       
   300 	// Increment the echosocket counter and client
       
   301 	iOwnerStep->iOwnerSuite->iScheduler->IncCount();
       
   302 
       
   303 	TName addrBuf;
       
   304 	iDestAddr.Output(addrBuf);
       
   305 	iOwnerStep->StepLog(KSockDetails,&iName,iSockNum,&addrBuf,iDestAddr.Port(),iPacketsToSend,iPacketSize);
       
   306 
       
   307 	TRequestStatus* pS = &iStatus;
       
   308 	User::RequestComplete(pS,KErrNone);
       
   309 
       
   310 	return KErrNone;
       
   311 	}
       
   312 
       
   313 
       
   314 
       
   315 void CEchoSocket::ConnectTcp()
       
   316 /**
       
   317  * Connects a TCP socket to the remote host.
       
   318  */
       
   319 	{
       
   320 	__ASSERT_ALWAYS(iProtocol==KProtocolInetTcp, User::Panic(KTxtCEchoSocket,KErrArgument));
       
   321 	iSocket.Connect(iDestAddr,iStatus);
       
   322 	iSafety->SetSafety();
       
   323 	iState = EReady;
       
   324 	SetActive();
       
   325 	}
       
   326 
       
   327 void CEchoSocket::BindUdp()
       
   328 /**
       
   329  * Binds a socket to its address
       
   330  */
       
   331 	{
       
   332 	__ASSERT_ALWAYS(KProtocolInetUdp == iProtocol, User::Panic(KTxtCEchoSocket,KErrArgument));
       
   333 
       
   334 	iSocket.Connect(iDestAddr,iStatus);
       
   335 	iSafety->SetSafety();
       
   336 	iState = EReady;
       
   337 	SetActive();
       
   338 	}
       
   339 
       
   340 
       
   341 
       
   342 void CEchoSocket::SendData()
       
   343 /**
       
   344  * Sends a packet on the socket and updates state information
       
   345  */
       
   346 	{
       
   347 	// Packet data
       
   348 	TBuf8<100> data;
       
   349 	// Write data to socket 
       
   350 	if (iProtocol == KProtocolInetTcp)
       
   351 		{
       
   352 		data.Format(_L8("TCP-packet[%S:%d] MultiHoming"), &iName, iPacketsToSend--);
       
   353 		}
       
   354 	else if (iProtocol == KProtocolInetUdp)
       
   355 		{
       
   356 		data.Format(_L8("UDP-packet[%S:%d] MultiHoming"), &iName, iPacketsToSend--);
       
   357 		}
       
   358 	iPtrWritn.Repeat( data );
       
   359 
       
   360 	iPtrRecvd.SetLength( iPtrWritn.Length() );
       
   361 
       
   362 	iSocket.Send(iPtrWritn,0,iStatus);
       
   363 	
       
   364 	iState = ESentData;
       
   365 	SetActive();
       
   366 	}
       
   367 
       
   368 void CEchoSocket::SendDataToClient()
       
   369 	{
       
   370 	iAcceptedConnection.Send(iPtrRecvd,0,iStatus);
       
   371 	
       
   372 	iState = ESentData;
       
   373 	SetActive();
       
   374 	}
       
   375 void CEchoSocket::RecvDataTcpListen()
       
   376 /** 
       
   377  * Receives data on socket
       
   378  *
       
   379  */
       
   380 	{
       
   381 	// Receive data
       
   382 	iSafety->SetSafety();
       
   383 	TInt expected = iPtrRecvd.Length();
       
   384     iAcceptedConnection.Read(iPtrRecvd, iStatus);
       
   385     iOwnerStep->StepLog(_L("Receiving Data TCP Listen %S:%i"),&iName, iSockNum);
       
   386 	iState = ERecvdData;
       
   387 	SetActive();
       
   388 	}
       
   389 
       
   390 
       
   391 
       
   392 void CEchoSocket::RecvData()
       
   393 /** 
       
   394  * Receives data on socket
       
   395  *
       
   396  */
       
   397 	{
       
   398 	// Receive data
       
   399 	iSafety->SetSafety();
       
   400 	TInt expected = iPtrRecvd.Length();
       
   401     if(iProtocol == KProtocolInetTcp)
       
   402         {
       
   403 	    iSocket.Read(iPtrRecvd, iStatus);
       
   404         }
       
   405     else if(iProtocol == KProtocolInetUdp)
       
   406         {
       
   407 	    iSocket.Recv(iPtrRecvd, 0, iStatus);
       
   408         }
       
   409 	if(expected != iPtrRecvd.Length())
       
   410 		{
       
   411 	    _LIT(KErrMsg, "%S: Expected to Recv %i octets, actual is %i");
       
   412 		iOwnerStep->StepLog(KErrMsg, &iName, expected, iPtrRecvd.Length());
       
   413 		}
       
   414 	iState = ERecvdData;
       
   415 	SetActive();
       
   416 	}
       
   417 
       
   418 TInt CEchoSocket::LogReport(TBool& aPassed, TInt& aNumSent, TInt& aUdpRate)
       
   419 /**
       
   420  * Allows a CEchoSocket to pass back its outcome
       
   421  * @param aPassed Did the test pass?
       
   422  * @param aUdpRate Percentage of UDP packets dropped
       
   423  * @return The last error state of the socket
       
   424  */
       
   425 	{
       
   426 	__ASSERT_ALWAYS(iState==EComplete,User::Panic(KTxtCEchoSocket,KErrNotReady));
       
   427 
       
   428 	aPassed=EFalse;
       
   429 	aNumSent = iPackets;
       
   430 	if (KProtocolInetTcp == iProtocol && iRecvdGood == iPackets)
       
   431 		{
       
   432 		aPassed=ETrue;
       
   433 		aUdpRate=0;
       
   434 		}
       
   435 	else
       
   436 		{
       
   437 		TInt dropped = 100;
       
   438 		if (iPackets != 0)	// No div/0 errs thanks...
       
   439 			// nL = nS - nR
       
   440 			// nL/nS = 1 - nR/nS 
       
   441 			dropped = 100 - ((100*iRecvdGood) / iPackets);
       
   442 
       
   443 		if (dropped <= iUDPTolerance)
       
   444 			aPassed=ETrue;
       
   445 		aUdpRate= dropped;
       
   446 		}
       
   447 	return iSockErr;
       
   448 	}
       
   449 
       
   450 
       
   451 void CEchoSocket::SafetyCall()
       
   452 /**
       
   453  * Allows the safety timer access, without becoming a friend class.
       
   454  */
       
   455 	{
       
   456 	if (iIsListener && (KProtocolInetTcp == iProtocol))
       
   457 		{
       
   458 		iAcceptedConnection.CancelAll();
       
   459 		}
       
   460 	
       
   461 	iSocket.CancelAll();
       
   462 	}
       
   463 void CEchoSocket::SetComplete()
       
   464 /**
       
   465  * Sets the socket to completion status.	
       
   466  */	
       
   467 	{
       
   468 	iSafety->Cancel();		
       
   469 	iSocket.CancelAll();
       
   470 	iSocket.Close();		
       
   471 	if(iIsListener && (KProtocolInetTcp == iProtocol))
       
   472 		{
       
   473 		iAcceptedConnection.CancelAll();
       
   474 		iAcceptedConnection.Close();		
       
   475 		}
       
   476 
       
   477 	
       
   478 
       
   479 
       
   480 	iSockErr = iStatus.Int();	// Record the last error for use by caller.
       
   481 	iStatus = KRequestPending;
       
   482 	iState = EComplete;
       
   483 	if(!IsActive() )
       
   484 		SetActive();
       
   485 	TRequestStatus* pS = &iStatus;
       
   486 	User::RequestComplete(pS,KErrNone);
       
   487 	
       
   488 	}
       
   489 
       
   490 
       
   491 
       
   492 
       
   493 
       
   494 CSafety::CSafety() : CActive(EPriorityNormal), iTime(CEchoSocket::SAFETY_TIMEOUT)
       
   495 	{
       
   496 	}
       
   497 
       
   498 
       
   499 CSafety::~CSafety()
       
   500 	{
       
   501 	Cancel();
       
   502 	iSafety.Close();
       
   503 	}
       
   504 
       
   505 CSafety* CSafety::NewL(CEchoSocket* aOwner)
       
   506 	{
       
   507 	CSafety* self = new(ELeave) CSafety;
       
   508 	CleanupStack::PushL(self);
       
   509 	self->ConstructL(aOwner);
       
   510 	CleanupStack::Pop();
       
   511 	return self;
       
   512 	}
       
   513 
       
   514 
       
   515 void CSafety::ConstructL(CEchoSocket* aOwner)
       
   516 	{
       
   517 	myOwner=aOwner;
       
   518 	iSafety.CreateLocal();
       
   519 	CEnhancedScheduler::Add(this);
       
   520 	}
       
   521 
       
   522 void CSafety::RunL()
       
   523 	{
       
   524 	myOwner->SafetyCall();
       
   525 	}
       
   526 
       
   527 
       
   528 void CSafety::DoCancel()
       
   529 	{
       
   530 	iSafety.Cancel();
       
   531 	}
       
   532 
       
   533 void CSafety::SetSafety()
       
   534 	{
       
   535 	__ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCEchoSocket, KErrAlreadyExists));
       
   536 	iSafety.After(iStatus, iTime);
       
   537 	SetActive();
       
   538 	}
       
   539 CSplitEchoSocket* CSplitEchoSocket::NewL()
       
   540 	{
       
   541 	CSplitEchoSocket* self = new (ELeave)CSplitEchoSocket();
       
   542 	CleanupStack::PushL(self);
       
   543 	self->ConstructL();
       
   544 	CEnhancedScheduler::Add(self);
       
   545 	CleanupStack::Pop(self);
       
   546 	return self;
       
   547 	}
       
   548 
       
   549 CSplitEchoSocket::CSplitEchoSocket() : CEchoSocket()
       
   550 	{
       
   551 	}
       
   552 
       
   553 CSplitEchoSocket::~CSplitEchoSocket()
       
   554 	{
       
   555 	}
       
   556 
       
   557 TInt CSplitEchoSocket::Echo(const TInetAddr& aDest, const TInetAddr& aSrc,
       
   558 							const TInt& aSize,	const TInt& aPackets, 
       
   559 							const TUint& aProto, const TInt& aTol,
       
   560 							TConnDetails* aConn, const TInt& aSockNum, 
       
   561 							const TBool aIsListener, CTS_MultiHomingStep* aStep)
       
   562 /**
       
   563  * Creates an Echo socket and runs it to completion or error
       
   564  * @param aSockServ The socket server to attach to
       
   565  * @param aDest The destination IP address
       
   566  * @param aSize The packet size to use in bytes
       
   567  * @param aPackets The number of packets to send
       
   568  * @param aProto The protocol to use
       
   569  * @param aTol The UDP data tolerance level
       
   570  * @return Error value for initialisation stage
       
   571  */
       
   572 	{
       
   573 	__ASSERT_ALWAYS(!IsActive(), User::Panic(KTxtCEchoSocket,KErrAlreadyExists));
       
   574 	__ASSERT_ALWAYS(aSize <= CTS_MultiHomingStep::MAX_PACKET_SIZE, User::Panic(KTxtCEchoSocket,KErrOverflow));
       
   575 	
       
   576 	// Remember the config
       
   577 	iDestAddr = aDest;
       
   578 	iSrcAddr = aSrc;
       
   579 	iPacketSize = aSize;
       
   580 	iPacketsToSend = aPackets;
       
   581 	iPackets = aPackets;
       
   582 	iProtocol = aProto;
       
   583 	iUDPTolerance = aTol;
       
   584 	iOwnerStep = aStep;
       
   585 	iTConnection = aConn;
       
   586 	iSockNum = aSockNum;
       
   587 
       
   588 	iIsListener = aIsListener;
       
   589 
       
   590 	TInt err = KErrNone;
       
   591 
       
   592 	iPtrWritn.SetLength(aSize);
       
   593 	iPtrRecvd.SetLength(aSize);
       
   594 
       
   595 	
       
   596 	if(iTConnection == 0)
       
   597 		return KErrGeneral;
       
   598 	// Open the socket for implicit or explicit case
       
   599 	if(iTConnection->iConnectionType != TConnDetails::implicitConn)
       
   600 		{
       
   601 		err = iSocket.Open( (iTConnection->iSocketServ), KAfInet, 
       
   602 					iProtocol == KProtocolInetTcp ? KSockStream : KSockDatagram, iProtocol,
       
   603 					(iTConnection->iConnection));
       
   604 		}
       
   605 	else
       
   606 		{
       
   607 		err = iSocket.Open( (iTConnection->iSocketServ), KAfInet, 
       
   608 					iProtocol == KProtocolInetTcp ? KSockStream : KSockDatagram, iProtocol);
       
   609 		}
       
   610 	if (err != KErrNone)
       
   611 		return err;			// No point going any further...
       
   612 
       
   613 	iSocket.Name(iName);
       
   614 	
       
   615 	if(iIsListener)	// Don't bind if we are only sending
       
   616 		{
       
   617 		err = iSocket.Bind(iSrcAddr);
       
   618 		iOwnerStep->StepLog(_L("Binding %S:%i"),&iName, iSockNum);
       
   619 		if(err != KErrNone)
       
   620 			return err;
       
   621 		
       
   622 		// Accept a single connection
       
   623 		if (iProtocol == KProtocolInetTcp)
       
   624 			{
       
   625 			iSocket.Listen(1);
       
   626 			iOwnerStep->StepLog(_L("Listening %S:%i"),&iName, iSockNum);
       
   627 			}
       
   628 		}
       
   629 
       
   630 	iState = EInitialised;
       
   631 	iStatus = KRequestPending;
       
   632 	SetActive();
       
   633 
       
   634 	// Increment the echosocket counter and client
       
   635 	iOwnerStep->iOwnerSuite->iScheduler->IncCount();
       
   636 
       
   637 	TName addrBuf;
       
   638 	iDestAddr.Output(addrBuf);
       
   639 	iOwnerStep->StepLog(KSockDetails,&iName,iSockNum,&addrBuf,iDestAddr.Port(),iPacketsToSend,iPacketSize);
       
   640 
       
   641 	TRequestStatus* pS = &iStatus;
       
   642 	User::RequestComplete(pS,KErrNone);
       
   643 
       
   644 	return KErrNone;
       
   645 	}
       
   646 
       
   647 
       
   648 void CSplitEchoSocket::RunL()
       
   649 	{
       
   650 	switch (iState)
       
   651 		{
       
   652 		case EInitialised:
       
   653 			if (KProtocolInetTcp == iProtocol)
       
   654 				{
       
   655 				if(iIsListener)
       
   656 					{
       
   657 					iAcceptedConnection.Open( (iTConnection->iSocketServ));
       
   658 					iSocket.Accept(iAcceptedConnection, iStatus);
       
   659 					iOwnerStep->StepLog(_L("Waiting for TCP accept on %S:%i"),&iName, iSockNum);
       
   660 					iSafety->SetSafety();
       
   661 					iState = EReady;
       
   662 					SetActive();
       
   663 					}
       
   664 				else
       
   665 					{
       
   666 					ConnectTcp();
       
   667 					iOwnerStep->StepLog(_L("Connecting TCP %S:%i"),&iName, iSockNum);
       
   668 					}
       
   669 				}
       
   670 			else if (KProtocolInetUdp == iProtocol)
       
   671 				{
       
   672 				if(iIsListener)
       
   673 					{
       
   674 					RecvData();
       
   675 					}
       
   676 				else
       
   677 					{
       
   678 					BindUdp();
       
   679 					iOwnerStep->StepLog(_L("Binding UDP %S:%i"), &iName, iSockNum);
       
   680 					}
       
   681 				}
       
   682 			break;	
       
   683 			
       
   684 		case EReady:
       
   685 			iSafety->Cancel();
       
   686 			if (iStatus.Int() == KErrNone)
       
   687 				{
       
   688 				if(iIsListener)
       
   689 					{
       
   690 					if (KProtocolInetTcp == iProtocol)
       
   691 						{
       
   692 						RecvDataTcpListen();
       
   693 						}
       
   694 					else
       
   695 						{
       
   696 						RecvData();
       
   697 						}
       
   698 					}
       
   699 				else
       
   700 					{
       
   701 					SendData();
       
   702 					}
       
   703 				}
       
   704 			else
       
   705 				{
       
   706 				iOwnerStep->StepLog(KErrConnectFailed,&iName,iSockNum, iStatus.Int());
       
   707 				SetComplete();
       
   708 				}
       
   709 			break;
       
   710 			
       
   711 		case ESentData:
       
   712 			iSafety->Cancel();
       
   713 			if (iStatus == KErrNone)
       
   714 				{
       
   715 				if(iIsListener)
       
   716 					{
       
   717 					if (KProtocolInetTcp == iProtocol)
       
   718 						{
       
   719 						RecvDataTcpListen();
       
   720 						}
       
   721 					else
       
   722 						{
       
   723 						RecvData();
       
   724 						}
       
   725 					}
       
   726 				else
       
   727 					{
       
   728 					iRecvdGood++;	// Fake that we've received all we should (sending socket doesn't receive)
       
   729 					// Blindly send, no receiving
       
   730 					if (iPacketsToSend>0)
       
   731 						{
       
   732 						SendData();
       
   733 						}
       
   734 					else
       
   735 						{
       
   736 						SetComplete();
       
   737 						}
       
   738 					}
       
   739 				}
       
   740 			else
       
   741 				{
       
   742 				iOwnerStep->StepLog(KErrSendFailed, &iName, iSockNum, iStatus.Int());
       
   743 				SetComplete();	// Couldn't send, so bit of a problem...
       
   744 				}
       
   745 			break;
       
   746 		
       
   747 		case ERecvdData:
       
   748 			iSafety->Cancel();
       
   749 			if(iIsListener && (iStatus.Int() == KErrEof) )
       
   750 				{
       
   751 				iRecvdGood++;
       
   752 				iStatus = KErrNone;
       
   753 				SetComplete();
       
   754 				}
       
   755 			else if(iStatus.Int() == KErrNone)
       
   756 				{
       
   757 				// Reset our consecutive count
       
   758 				iConsecRecvTimeOuts = 0;
       
   759  				if (iIsListener)
       
   760 					{
       
   761 					iRecvdGood++;
       
   762 					
       
   763 					if (iPacketsToSend > 0)
       
   764 						{
       
   765 						if(iIsListener)
       
   766 							{
       
   767 							if (KProtocolInetUdp == iProtocol)
       
   768 								{
       
   769 								RecvData();
       
   770 								}
       
   771 							else
       
   772 								{
       
   773 								RecvDataTcpListen();		
       
   774 								}
       
   775 							}
       
   776 						else 
       
   777 							{
       
   778 							SendData();	
       
   779 							}
       
   780 						}
       
   781 					else
       
   782 						{
       
   783 						SetComplete();
       
   784 						}
       
   785 					}
       
   786 				else
       
   787 					{
       
   788 					// Try reading again, usualy happens because of a timeout
       
   789 					iOwnerStep->StepLog(KErrPacketsDiff, &iName, iSockNum);
       
   790 					RecvData();
       
   791 					}				
       
   792 				}
       
   793 			else if (KErrCancel == iStatus.Int()) // We cancelled our receive
       
   794 				{
       
   795 				iConsecRecvTimeOuts++;
       
   796 				iOwnerStep->StepLog(_L("Receive timeout on %S:%i,%d"),&iName, iSockNum,
       
   797 					iConsecRecvTimeOuts);
       
   798 				
       
   799 				iOwnerStep->StepLog(_L("%d received packets, %d still to send"),iRecvdGood, iPacketsToSend);
       
   800 					
       
   801 				if ( (iPacketsToSend - iUDPTolerance) > 0 && iConsecRecvTimeOuts < MAX_CONSEC_TIMEOUT)
       
   802 					{
       
   803 					if (iIsListener)
       
   804 						{
       
   805 						if (KProtocolInetUdp == iProtocol)
       
   806 							{
       
   807 							RecvData();
       
   808 							}
       
   809 						else
       
   810 							{
       
   811 							RecvDataTcpListen();		
       
   812 							}
       
   813 						}
       
   814 					else
       
   815 						{
       
   816 						if (KProtocolInetTcp == iProtocol)
       
   817 							SendData();
       
   818 						}
       
   819 					}
       
   820 				else
       
   821 					{
       
   822 					SetComplete();
       
   823 					}
       
   824 				}
       
   825 			else
       
   826 				{
       
   827 				TPtrC errorText = CLog::EpocErrorToText(iStatus.Int());
       
   828 				iOwnerStep->StepLog(KErrRecvFailed, &iName, iSockNum, &errorText);
       
   829 				SetComplete();
       
   830 				}
       
   831 			break;
       
   832 
       
   833 			
       
   834 		case EComplete:
       
   835 			iOwnerStep->iOwnerSuite->iScheduler->DecCount();
       
   836 			if(0 == iOwnerStep->iOwnerSuite->iScheduler->GetCount())
       
   837 				CEnhancedScheduler::Stop();
       
   838 			break;
       
   839 
       
   840 		default:
       
   841 			iOwnerStep->StepLog(KTxtWhatHappened);
       
   842 			break;
       
   843 		
       
   844 		}
       
   845 	}
       
   846 
       
   847 void CSplitEchoSocket::RecvData()
       
   848 /** 
       
   849  * Receives data on socket
       
   850  *
       
   851  */
       
   852 	{
       
   853 	// Receive data
       
   854 	iSafety->SetSafety();
       
   855 	TInt expected = iPtrRecvd.Length();
       
   856     if(iProtocol == KProtocolInetTcp)
       
   857         {
       
   858 	    iSocket.Read(iPtrRecvd, iStatus);
       
   859         }
       
   860     else if(iProtocol == KProtocolInetUdp)
       
   861         {
       
   862         if (iIsListener)
       
   863         	{
       
   864             //iSocket.RecvFrom(iPtrRecvd, iSrcAddr, 0, iStatus);
       
   865             iSocket.Recv(iPtrRecvd, 0, iStatus);
       
   866             iOwnerStep->StepLog(_L("Receiving UDP Packet..."));
       
   867         	}
       
   868         else
       
   869         	{
       
   870         	iSocket.Recv(iPtrRecvd, 0, iStatus);
       
   871         	}
       
   872         }
       
   873     if (iIsListener)
       
   874     	iPacketsToSend--;	// Decrement this
       
   875 	
       
   876     iState = ERecvdData;
       
   877 	SetActive();
       
   878 	}
       
   879