/*
* Copyright (c) 2005-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:   
* This file was autogenerated by rpcgen, but should be modified by the developer.
* Make sure you don't use the -component_mod flag in future or this file will be overwritten.
* Fri Sep 12 12:11:08 2003
* System Includes
*
*/




#include <stdio.h>
#include <assert.h>
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif


/****************************************************************************************
 * 
 * Local Includes
 * 
 ***************************************************************************************/
#include "CSvcMobster.h"
#include "CSMobster.h"


/****************************************************************************************
 * 
 * Definitions
 * 
 ***************************************************************************************/
#define MAXLOGNAME		64
#ifndef WIN32
#define _snprintf               snprintf
#define ADDRESS_INTEGER         s_addr
#endif

/****************************************************************************************
 * 
 * Implementation
 * 
 ***************************************************************************************/
CSMobster::CSMobster()
{
}

CSMobster::~CSMobster()
{
	stopdevice( 0 );
}

int CSMobster::GetKey()
{
	return iKey;
}

void CSMobster::SetKey( int aKey )
{
	iKey = aKey;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: cstr_startdevice
 * 
 ***************************************************************************************/
int CSMobster::cstr_startdevice( TDeviceDesc aDeviceDesc )
{
	int rv, err, errcode;

	// set the state info for this object
	memset( &iDeviceDesc, 0, sizeof(iDeviceDesc) );
	iDeviceDesc.iDatalinkConfig = aDeviceDesc.iDatalinkConfig;
	iDeviceDesc.iFilterConfig = aDeviceDesc.iFilterConfig;
	iDeviceDesc.iMTID = iKey;
	iDeviceDesc.iTEID = INVALID_DEVICE_ID;
	iDeviceDesc.iDeviceStatus = CS_INACTIVE;
	iDeviceDesc.iDeviceExitReason = DER_INVALID;

	// start a phone in another thread, note that if it fails the call still succeeds, we
	// treat this as the phone starting and then ending asynchronously. The main motivation
	// for this is that it allows us to get all the debug info out.
	err = iPhone.StartPhone( iKey, iDeviceDesc.iDatalinkConfig, iDeviceDesc.iFilterConfig, &errcode );
	if( err != MTL_SUCCESS ) {
		iDeviceDesc.iDeviceExitReason = DER_START_PHONE_FAILED;
		iDeviceDesc.iDeviceExitSubReason = err;
		iDeviceDesc.iDeviceExitDetail = errcode;
		iDeviceDesc.iDeviceStatus = CS_CLOSED;
	} else {
		iDeviceDesc.iDeviceStatus = CS_ACTIVE;
	}

	// we now just wait for the other thread to get the channel connection
	rv = ERR_NONE;
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: dstr_removedevice
 * 
 ***************************************************************************************/
int CSMobster::dstr_removedevice( int aArgs, int *aDeleteInstance )
{
	int rv;
	MTStatus mtstatus;

	// if the phone was CS_ACTIVE last time then we have to check that it hasn't 
	// change on its own accord.
	if( iDeviceDesc.iDeviceStatus == CS_ACTIVE ) {
		mtstatus = iPhone.GetStatus();
		if( mtstatus == MTS_SHUTDOWN_ALL ) {
			iDeviceDesc.iDeviceStatus = CS_CLOSED;
		}
	}

	// cannot remove the device unless it is in the closed state
	if( iDeviceDesc.iDeviceStatus != CS_CLOSED ) {
		*aDeleteInstance = 0;
		return ERR_INVALIDSTATE;
	}

	// otherwise let everything be cleaned up
	*aDeleteInstance = 1;
	rv = ERR_NONE;
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: getdeviceinfo
 * 
 ***************************************************************************************/
TDeviceDesc CSMobster::getdeviceinfo( int aArgs )
{
	struct sockaddr_in sockaddr;
	TDeviceDesc rv;
	char *addr;
	MTStatus mtstatus;

	// if the phone was CS_ACTIVE last time then we have to check that it hasn't 
	// change on its own accord.
	if( iDeviceDesc.iDeviceStatus == CS_ACTIVE ) {
		mtstatus = iPhone.GetStatus();
		if( mtstatus == MTS_SHUTDOWN_ALL ) {
			iDeviceDesc.iDeviceStatus = CS_CLOSED;
		}
	}

	// copy the static values from the local version
	rv = iDeviceDesc;

	// update the addresses from the MT
	iPhone.GetLocalUUAddress( &sockaddr );
	sprintf( rv.iLocalAirInterfacePort, "%d", ntohs(sockaddr.sin_port) );
	iPhone.GetRemoteUUAddress( &sockaddr );
	sprintf( rv.iRemoteAirInterfacePort, "%d", ntohs(sockaddr.sin_port) );
	addr = inet_ntoa( sockaddr.sin_addr );
	_snprintf( rv.iRemoteAirInterfaceAddress, MAXADDRLEN, "%s", addr ); 

	// done
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: getdevicelog
 * 
 ***************************************************************************************/
TVarData CSMobster::getdevicelog( int aArgs )
{
	TVarData rv;
	CLog *log;
	int logsize;

	// init the rv
	rv.TVarData_len = 0;
	rv.TVarData_val = NULL;

	// get the log from the device
	log = iPhone.GetLog();

	// get the size of the log and allocate the space
	logsize = log->CalculateLogSize();
	if( logsize == 0 ) {
		return rv;
	}
	rv.TVarData_val = (char*)malloc( logsize );
	rv.TVarData_len = logsize;

	// copy the log into the buffer
	log->PrintLogToBuffer( logsize, rv.TVarData_val );

	// close up the file and return data
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: stopdevice
 * 
 ***************************************************************************************/
int CSMobster::stopdevice( int aArgs )
{
	int rv, err;

	// no phone should be in the ps_inactive state (non-atomically)
	assert( iDeviceDesc.iDeviceStatus != CS_INACTIVE );

	// if we are in the closed state already then return invalid state
	if( iDeviceDesc.iDeviceStatus == CS_CLOSED ) {
		rv = ERR_INVALIDSTATE;
		return rv;
	}

	// if we are in the active state then stop the phone -- if stop fails then we 
	// return without changing the state -- this means that the phone should only
	// return an error from StopPhone() if it is a transient error.
	assert( iDeviceDesc.iDeviceStatus == CS_ACTIVE );
	err = iPhone.StopPhone();
	if( err != 0 ) {
		rv = ERR_STOPFAILED;
		return rv;
	}
	iDeviceDesc.iDeviceExitReason = DER_USER_REQUEST;
	iDeviceDesc.iDeviceExitSubReason = 0;
	iDeviceDesc.iDeviceExitDetail = 0;
	iDeviceDesc.iDeviceStatus = CS_CLOSED;

	// return success
	rv = ERR_NONE;
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: setremoteuuaddress
 * 
 ***************************************************************************************/
int CSMobster::setremoteuuaddress( TUUAddress aArgs )
{
	int rv, err;
	struct sockaddr_in sockaddr;

	// call the phone
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_addr.ADDRESS_INTEGER = aArgs.iRemoteAddress;
	sockaddr.sin_port = aArgs.iRemotePort;
	err = iPhone.SetRemoteUUAddress( sockaddr );

	// translate cphone error to mobster
	assert( err == MTL_SUCCESS );
	rv = ERR_NONE;
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: settesocket
 * 
 ***************************************************************************************/
int CSMobster::settesocket( int aSock )
{
	MTError merr;

	// pass the socket to the phone
	merr = iPhone.SetTeSocket( aSock );

	// 	translate the errors
	return ((merr == MTL_SUCCESS) ? ERR_NONE : ERR_CHANNEL_SOCKET_ALREADY_SET);
}
