// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// csockethandler.cpp
// 
//
/**
@file
@internalTechnology
*/

//User include
#include "csockethandler.h"

#include <mdns/cdnsmessagecomposerparser.h>
#include <mdns/cdnsmessage.h>
__FLOG_STMT(_LIT8(KComponent,"MDNSServer");)
/**
Two-phase construction method
@param 	aSocket Reference to  RSocket
@param 	aObserver Reference to  MSocketHandlerObserver used to notify the client.
@param 	aOperation TSocketOperation specfies the operation socket should perform.
@return a pointer to the requested socket handler object
*/

CSocketHandler* CSocketHandler::NewL(RSocket& aSocket, MSocketHandlerObserver& aObserver, TSocketOperation aOperation)
 	{
 	CSocketHandler* self = new (ELeave)CSocketHandler(aSocket, aObserver, aOperation);
 	CleanupStack::PushL(self);	
 	self->ConstructL();
 	CleanupStack::Pop();
 	return self;
 	}
 	
 
 /**
 Destructor
 */
CSocketHandler::~CSocketHandler()
	{
	__FLOG(_L8("CSocketHandler::~CSocketHandler - Entry"));
	Cancel();
	delete iPacketBuffer;
	__FLOG(_L8("CSocketHandler::~CSocketHandler - Exit"));
	__FLOG_CLOSE;
	}
	

/**
This to activate the socket to perform either send or recieve based on the operation set.
@param aParams Reference to TSocketHandlerParams containing operation,packet and address
@return void
*/	
void CSocketHandler::Activate ( const TSocketHandlerParams& aParams )
	{
	__FLOG(_L8("CSocketHandler::Activate - Entry"));
	iOperation = static_cast < TSocketOperation > ( aParams.iArgs[0] );
	switch ( iOperation )
		{
		case ESocketSend:
			{
			iPacketPtr.Zero();
			HBufC8* bufChain = reinterpret_cast < HBufC8* > ( aParams.iArgs[1] );
			iLength = 0;
			iSocket.Send(*bufChain, KDefaultFlags, iStatus, iLength );
			}
		break;
		
		case ESocketSendTo:
			{
			iPacketPtr.Zero();
			RBuf8* bufChain = reinterpret_cast < RBuf8* > ( aParams.iArgs[1] );
			iSockAddr = *(reinterpret_cast < TSockAddr* > ( aParams.iArgs[2] ));
			iLength = 0;
			iSocket.SendTo ( *bufChain, iSockAddr, KDefaultFlags, iStatus, iLength );
			}
		break;

		case ESocketRecieve:
			{
			iPacketPtr.Zero();
			iSocket.Recv (iPacketPtr, KDefaultFlags, iStatus );
			}
		break;

		case ESocketRecieveFrom:
			{
			iPacketPtr.Zero();
			iSocket.RecvFrom ( iPacketPtr, iSockAddr, KDefaultFlags, iStatus );
			}
		break;

		default:
			User::Invariant ();
		};
	
	SetActive();
	__FLOG(_L8("CSocketHandler::Activate - Exit"));
	}
/**

*/
void CSocketHandler::CompleteSelf ( TInt aError )
	{
	__FLOG(_L8("CSocketHandler::CompleteSelf - Entry"));
    TRequestStatus* pStat = &iStatus;
    User::RequestComplete ( pStat, aError );
	SetActive ( );
	__FLOG(_L8("CSocketHandler::CompleteSelf - Exit"));
    }
/**
Constructor
*/
CSocketHandler::CSocketHandler(RSocket& aSocket, MSocketHandlerObserver& aObserver, TSocketOperation aOperation):CActive ( EPriorityNormal ),iSocket(aSocket),iObserver(aObserver),iOperation(aOperation),iPacketPtr(NULL,0)
	{
		
	}
/**
Constructs a heap to hold the packet of almost 9k size
*/
void CSocketHandler::ConstructL()
	{
	__FLOG_OPEN(KMDNSSubsystem, KComponent);
	__FLOG(_L8("CSocketHandler::ConstructL - Entry"));
	// Allocate a 9K buffer to contain the biggest mDNS packet allowable
	iPacketBuffer = HBufC8::NewL(KMaxDnsPacketSize);
	iPacketPtr.Set(iPacketBuffer->Des());	
	CActiveScheduler::Add(this);
	__FLOG(_L8("CSocketHandler::ConstructL - Exit"));
	}

/**
cancels the current operation
*/
void CSocketHandler::CancelCurrent()
	{
	__FLOG(_L8("CSocketHandler::CancelCurrent - Entry"));
	switch ( iOperation )
		{
		case ESocketSend:	
		case ESocketSendTo:
			iSocket.CancelSend ();
		break;

		case ESocketRecieve:
		case ESocketRecieveFrom:
			iSocket.CancelRecv ();
		break;

		};
	__FLOG(_L8("CSocketHandler::CancelCurrent - Exit"));
	}
/**
Notifies the client with parameters based on the operation.
a.	Returns the packet and addres for recieve operation.
b.	returns only length of data send for send operation.
*/
void CSocketHandler::NotifyCompletionL( )
	{
	__FLOG(_L8("CSocketHandler::NotifyCompletionL - Entry"));
	switch ( iOperation )
		{
		case ESocketSend:	
			{
			iObserver.OnCompletionL(iPacketPtr,NULL,iLength());
			break;
			}
	
		case ESocketSendTo:
			{
			iObserver.OnCompletionL(iPacketPtr,iSockAddr,iLength());
			break;
			}
					
		case ESocketRecieve:
		case ESocketRecieveFrom:		
			{

			iObserver.OnCompletionL(iPacketPtr,iSockAddr,iLength());
			break;
			}
	
		};
	__FLOG(_L8("CSocketHandler::NotifyCompletionL - Exit"));
	}
/**
Notifies the client after the send or recieve  	
//Derived from CActive
*/
void CSocketHandler::RunL()
	{
	__FLOG(_L8("CSocketHandler::RunL - Entry"));
	TInt err = iStatus.Int ();
	if ( err == KErrNone )
		{
		NotifyCompletionL();
		}
	else
		{
		iObserver.OnError ( err );
		}
	__FLOG(_L8("CSocketHandler::RunL - Exit"));
	}
	

/**
Derived from CActive
Cancellation of an outstanding request.
*/	
void CSocketHandler::DoCancel()
	{
	__FLOG(_L8("CSocketHandler::DoCancel - Entry"));
	CancelCurrent ();
	__FLOG(_L8("CSocketHandler::DoCancel - Exit"));
	}


	
/**
Handles any leave from the RunL
@param aError Error with which Runl leaves
@return error 
*/	
TInt CSocketHandler::RunError(TInt /*aError*/)
	{
	__FLOG(_L8("CSocketHandler::RunError - Entry"));
	//__ASSERT_DEBUG(aError,User::Invariant());
	//Ignore any leave from RSocket
	__FLOG(_L8("CSocketHandler::RunError - Exit"));
	return KErrNone;
	}
