diff -r 000000000000 -r 3da2a79470a7 testexecmgmt/ucc/Source/MobileTermination/CTCPTEChannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecmgmt/ucc/Source/MobileTermination/CTCPTEChannel.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,283 @@ +/* +* 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: +* System Includes +* +*/ + + + +#include +#include +#ifndef WIN32 +#include +#include +#endif + + +/******************************************************************************* + * + * Local Includes + * + ******************************************************************************/ +#include "CTCPTEChannel.h" + + +/******************************************************************************* + * + * Definitions + * + ******************************************************************************/ +#ifndef WIN32 +#define SOCKET_ERROR (-1) +#define INVALID_SOCKET (-1) +#define Sleep(x) sleep(x/1000) +#else +#define SHUT_RDWR SD_BOTH +#endif + + +/******************************************************************************* + * + * Macro Functions + * + ******************************************************************************/ +#ifndef WIN32 +#define closesocket(x) (shutdown(x,SHUT_RDWR),close(x)) +#endif + + +/******************************************************************************* + * + * Constructor -- initialise all state + * + ******************************************************************************/ +CTcpTeChannel::CTcpTeChannel( TPhoneData *aPhoneData, CLog *aLog ) +{ + // verify args + assert( aPhoneData != NULL ); + assert( aLog != NULL ); + + // initialise state + iPhoneData = aPhoneData; + iDatalink = NULL; + iFilter = NULL; + iLog = aLog; + iSock = INVALID_SOCKET; + iStreamBuffer[0] = 0; + iExitFlag = 0; + iSocketSetFlag = 0; +} + +CTcpTeChannel::~CTcpTeChannel() +{ + assert( iSock == INVALID_SOCKET ); +} + + +/******************************************************************************* + * + * PUBLIC METHOD: RPC-THREAD. SetDatalink, called by the main setup call in + * cphone - links up all the bits. + * + ******************************************************************************/ +void CTcpTeChannel::SetDatalink( IProcessData *aDatalink ) +{ + iDatalink = aDatalink; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: RPC-THREAD. SetFilter, called by the main setup call in + * cphone - links up all the bits. + * + ******************************************************************************/ +void CTcpTeChannel::SetFilter( IFilter *aFilter ) +{ + iFilter = aFilter; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: SERVER-THREAD: + * + ******************************************************************************/ +TChannelError CTcpTeChannel::SetSocket( int aSocket ) +{ + // check that the socket is sane + assert( aSocket >= 0 ); + + // check that we haven't already set if + if( iSocketSetFlag != 0 ) { + return CE_SOCKET_ALREADY_SET; + } + + // ok - set the socket + iSock = aSocket; + iSocketSetFlag = 1; + return CE_NONE; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: LISTEN-THREAD: ListenOnChannel. This is the entry point for + * the listening thread. It sits in the loop below and passes all received data + * to the datalink layer. + * + ******************************************************************************/ +TChannelError CTcpTeChannel::ListenOnChannel( int *aErrCode ) +{ + TDataPathError derr; + int err; + int errcode; + + // check the params + assert( aErrCode != NULL ); + *aErrCode = 0; + + // listen on the socket until it closes + while( 1 ) { + + // if the socket is not defined then just wait for it + if( iSock == INVALID_SOCKET ) { + Sleep( 1000 ); + if( iExitFlag != 0 ) { + return CE_NONE; + } + continue; + } + + // read from socket if it is defined + err = recv( iSock, iStreamBuffer, KBUFFSIZE, 0 ); + + // if the socket has been closed then cleanup and return + if( err == 0 ) { + closesocket( iSock ); + iSock = INVALID_SOCKET; + return CE_NONE; + } + + // if an error has occured then report it and cleanup + if( err == SOCKET_ERROR ) { + *aErrCode = GetSocketError(); + closesocket( iSock ); + iSock = INVALID_SOCKET; + return CE_RECEIVE_FAILED; + } + + // pass the data received through the filters. + // : the control flow below allows the filter to analyse the data, and also change + // the data in-place. However, it doesn't allow the interface to change the size of the + // data (limiting the modifications it can make). This isn't a problem now since no + // filters do this -- but when this is needed it should be implemented here, and in the same + // place in the uu interface. + if( iFilter != NULL ) { + iFilter->ProcessOutgoingData( iStreamBuffer, err ); + } + + // Now pass the data through to the datalink layer. A datalink layer MUST be + // defined if the socket is defined. + assert( iDatalink != NULL ); + derr = iDatalink->ProcessTEData( iStreamBuffer, err, &errcode ); + if( derr != DPE_NONE ) { + iLog->WriteLogEntry( SV_WARNING, "CTcpTeChannel::ListenOnChannel", "ProcessTEData returned error", derr, errcode ); + } + } + + // should never get here + assert( !"INVALID CODE PATH" ); + return CE_NONE; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: MAIN-THREAD: StopChannel. This closes the socket (if open) + * which will force the recv to return 0 and the listen-thread will return. It + * also sets the exit flag for when we want to stop the channel before it + * really even started (poor thing). + * + ******************************************************************************/ +void CTcpTeChannel::StopChannel() +{ + // close the socket + if( iSock != INVALID_SOCKET ) { + closesocket( iSock ); + iSock = INVALID_SOCKET; + } + + // set the exit flag + iExitFlag = 1; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: AIR INTERFACE THREAD: SendPacket. This is called by the data + * link layer when it receives some data from the air interface that it now + * decides to forward on. + * + ******************************************************************************/ +TDataPathError CTcpTeChannel::SendPacket( char *data, int len, int *aErrCode ) +{ + int err; + int bytes_to_send; + int bytes_sent; + + // check params + assert( aErrCode != NULL ); + *aErrCode = 0; + + // if there is no connection then return. This is not unexpected or bad so + // no error is returned. + if( iSock == INVALID_SOCKET ) { + return DPE_NONE; + } + + // otherwise send data + bytes_to_send = len; + bytes_sent = 0; + while( bytes_sent < bytes_to_send ) { + err = send( iSock, &(data[bytes_sent]), bytes_to_send - bytes_sent, 0 ); + if( err == -1 ) { + *aErrCode = GetSocketError(); + closesocket( iSock ); + iSock = INVALID_SOCKET; + iSocketSetFlag = 0; + return DPE_SEND_FAILED; + } + bytes_sent += err; + } + + // success + return DPE_NONE; +} + + +/******************************************************************************* + * + * PRIVATE METHODS: HELPER FUNCTIONS + * + ******************************************************************************/ +int CTcpTeChannel::GetSocketError() +{ +#ifdef WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +}