/**
   Receive data on a socket via RecvFrom

   @param aSocket The socket to recevie data from
   @param aDesc Descriptor to receive the data into
   @param anAddress On success, contains the address from which data was received
   @return ETrue on success, EFalse on failure
*/
TBool CEsockTest9_6::PerformRecv( RSocket& aSocket, TDes8& aDesc, TSockAddr& anAddress )
	{
	TRequestStatus socketStatus;

	aSocket.RecvFrom( aDesc, anAddress, 0, socketStatus );
	WaitFor( socketStatus, KTimerPeriod );

	Logger().WriteFormat(_L("UDP Recv returns %d"), socketStatus.Int() );

	if( socketStatus == KRequestPending )
		{
		aSocket.CancelRecv();
		Logger().WriteFormat(_L("Timeout on UDP Recv"));
		User::WaitForRequest( socketStatus );
		return EFalse;
		}

	if( socketStatus != KErrNone )
		{
		Logger().WriteFormat(_L("UDP Recv failed with error %d"), socketStatus.Int() );
		return EFalse;
		}

	return ETrue;
	}
void CUdpSocket::StartReceiving()
{
	/* Clear buffer */
	iBufRx.Zero();

	if (!IsActive())
		SetActive();

	iSocket.RecvFrom(iBufRx, iSource, 0, iStatus);
}
int ILibSocketWrapper_recvfrom(int socketObject, char *buffer, int bufferLength, struct sockaddr *src)
{
	RSocket *s = (RSocket*)SocketArray[socketObject];
	TRequestStatus status;
	TInetAddr addr;
	int RetVal=0;
	RBuf8 *buf = new RBuf8();
	
	if(buf->Create(bufferLength)==KErrNone)
	{
		TProtocolDesc aProtocol;
		
		s->Info(aProtocol);
		if(aProtocol.iSockType==KSockStream)
		{
			s->RemoteName(addr);
			((struct in_addr*)src->sa_data)->s_addr = ntohl(addr.Address());
			src->sa_port = htons(addr.Port());
			RetVal = ILibSocketWrapper_recv(socketObject, buffer, bufferLength);
		}
		else
		{
			s->RecvFrom(*buf,addr,(unsigned int)0,status);
			User::WaitForRequest(status);
			if(status!=KErrNone)
			{
				RetVal = 0;
			}
			else
			{
				((struct in_addr*)src->sa_data)->s_addr = ntohl(addr.Address());
				src->sa_port = htons(addr.Port());
				Mem::Copy(buffer,buf->Ptr(),buf->Length());
				RetVal = buf->Length();
			}
		}
	}
	buf->Close();
	delete buf;
	return(RetVal);
}
enum TVerdict CTestStepNullAgtLoopbackTest::doTestStepL(void)
{
    __UHEAP_MARK;

    TInt r;                // the result of various operations
    TRequestStatus status; // status of asynchronous ops

    RSocketServ server;    // connection paraphanelia
    RConnection connection;
    RSocket socket;

    TInetAddr dest;
    dest.SetAddress(KDummyNifLocalAddressBase + 4);
    dest.SetPort(KPortNo);

    TBuf8<KBufferLength> buffer;

    // connect to the socket server
    r = server.Connect();
    TESTEL(r == KErrNone, r);
    CleanupClosePushL(server);

    // this is why we needed a socket server...
    r = connection.Open(server, KAfInet);
    TESTEL(r == KErrNone, r);
    CleanupClosePushL(connection);

    // start the connection up (outgoing)
    connection.Start(status);
    User::WaitForRequest(status);
    TESTEL(status.Int() == KErrNone, status.Int());

    // open a udp socket
    r = socket.Open(server, KAfInet, KSockDatagram, KProtocolInetUdp);
    TESTEL(r == KErrNone, r);
    CleanupClosePushL(socket);
    TESTL(socket.SetOpt(KSoReuseAddr, KSolInetIp, 1)==KErrNone);
    // set the source port number - otherwise will panic cos it's zero
    r = socket.SetLocalPort(KPortNo);
    TESTEL(r == KErrNone, r);

    // build some data to send on the socket
    // this is an ICMP ping request apparently
    buffer.SetMax();
    buffer.FillZ();
    buffer[0] = (TUint8) 0x8;		// ICMP type = 8
    buffer[1] = (TUint8) 0x0;		// ICMP code = 0
    buffer[2] = (TUint8) 0xF7;		// ICMP checksum high byte
    buffer[3] = (TUint8) 0xFF;		// ICMP checksum low byte
    // NB the rest of the buffer is zero
    // hence the checksum (0xFFFF - 0x800) since 0x8
    // is the only non-zero element of the buffer

    // send the data out over the socket
    socket.SendTo(buffer, dest, 0, status);
    User::WaitForRequest(status);
    TESTEL(status.Int() == KErrNone, status.Int());

    buffer.Zero();
    // I expect to get the data looped back from the dummy NIF
    socket.RecvFrom(buffer, dest, 0, status);
    User::WaitForRequest(status);
    TESTEL(status.Int() == KErrNone, status.Int());

    // check that what we sent is what we got back
    if (status.Int() == KErrNone)
    {
        // if the receive times out and we access buffer we get a panic
        TEST(buffer[0] == 0x08);
        TEST(buffer[1] == 0x00);
        TEST(buffer[2] == 0xF7);
        TEST(buffer[3] == 0xFF);
    }

    // close the socket
    socket.Shutdown(RSocket::ENormal, status);
    User::WaitForRequest(status);
    TESTEL(status.Int() == KErrNone, status.Int());
    CleanupStack::Pop();

    // force the destruction of the connection
    r = connection.Stop();
    TESTEL(r == KErrNone, r);
    CleanupStack::Pop();

    // close the socket server
    server.Close();
    CleanupStack::Pop();

    __UHEAP_MARKEND;

    return iTestStepResult;
}