diff -r 000000000000 -r 3da2a79470a7 testexecmgmt/ucc/Source/MobileTermination/CUDPAirInterface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecmgmt/ucc/Source/MobileTermination/CUDPAirInterface.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,313 @@ +/* +* 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 +#include +#ifndef WIN32 +#include +#include +#endif + + +/******************************************************************************* + * + * Local Includes + * + ******************************************************************************/ +#include "CUDPAirInterface.h" + + +/******************************************************************************* + * + * Definitions + * + ******************************************************************************/ +#ifndef WIN32 +#define SOCKET_ERROR (-1) +#define INVALID_SOCKET (-1) +#define ADDRESS_INTEGER s_addr +#define closesocket(x) (shutdown(x,SHUT_RDWR),close(x)) +#else +typedef int socklen_t; +#endif + + +/******************************************************************************* + * + * Macro Functions + * + ******************************************************************************/ + + +/******************************************************************************* + * + * Constructor - sets the passed pointers and sets the state to disabled + * + ******************************************************************************/ +CUDPAirInterface::CUDPAirInterface( TPhoneData *aPhoneData, CLog *aLog ) +{ + // verify parameters + assert( aPhoneData != NULL ); + assert( aLog != NULL ); + + // init state + iPhoneData = aPhoneData; + iProcessData = NULL; + iLog = aLog; + iFilter = NULL; + memset( &iRemoteAddress, 0, sizeof(iRemoteAddress) ); + memset( &iLocalAddress, 0, sizeof(iLocalAddress) ); + iSockIncoming = INVALID_SOCKET; + iSockOutgoing = INVALID_SOCKET; + iExitFlag = 0; + iRemoteAddressValid = 0; +} + +CUDPAirInterface::~CUDPAirInterface( ) +{ + // check the status of the sockets + assert( iSockIncoming == INVALID_SOCKET ); + assert( iSockOutgoing == INVALID_SOCKET ); +} + + +/******************************************************************************* + * + * PUBLIC METHOD: LISTEN-THREAD: ListenOnInterface. Binds to local port and + * then starts listening on this port for more incoming data. Any incoming data + * is then sent to the datalink layer. + * + ******************************************************************************/ +TAirInterfaceError CUDPAirInterface::ListenOnInterface( int *aErrCode ) +{ + TDataPathError derr; + int err, errcode; + struct sockaddr_in remote_recv_addr; + socklen_t addrlen; + + // verify params + assert( aErrCode != NULL ); + *aErrCode = 0; + + // check that the local port is invalid + assert( iSockIncoming == INVALID_SOCKET ); + + // create the listening socket + iSockIncoming = socket( AF_INET, SOCK_DGRAM, 0 ); + if( iSockIncoming == INVALID_SOCKET ) { + *aErrCode = GetSocketError(); + return AIE_SOCKET_FAILED; + } + + // if the exit flag is set then exit now + if( iExitFlag != 0 ) { + closesocket( iSockIncoming ); + iSockIncoming = INVALID_SOCKET; + return AIE_NONE; + } + + + // bind the listening socket -- bind to an ephemeral port + iLocalAddress.sin_family = AF_INET; + iLocalAddress.sin_port = htons(0); + iLocalAddress.sin_addr.ADDRESS_INTEGER = INADDR_ANY; + err = bind( iSockIncoming, (struct sockaddr*)&iLocalAddress, sizeof(iLocalAddress) ); + + // get the allocated port info + addrlen = sizeof(iLocalAddress); + err = getsockname( iSockIncoming, (sockaddr*)&iLocalAddress, &addrlen ); + assert( err == 0 ); + + // check for errors during the bind + if( err != 0 ) { + closesocket( iSockIncoming ); + iSockIncoming = INVALID_SOCKET; + *aErrCode = GetSocketError(); + return AIE_BIND_FAILED; + } + + // use the listening socket as the outgoing socket -- no reason we can't do + // this. It also means that we know the source port of the outgoing datagrams + // and hence we can do some proper NISTNET stuff + iSockOutgoing = iSockIncoming; + + // read from the socket until an error occurs (this may be induced by another + // thread closing the socket) + while( 1 ) { + + // now read from the socket + memset( &remote_recv_addr, 0, sizeof(remote_recv_addr) ); + addrlen = sizeof(remote_recv_addr); + err = recvfrom( iSockIncoming, iPacketBuffer, KPCKTBUFFSIZE, 0, (struct sockaddr*)&remote_recv_addr, &addrlen ); + + // check for errors + if( err == SOCKET_ERROR ) { + closesocket( iSockIncoming ); + iSockIncoming = iSockOutgoing = INVALID_SOCKET; + *aErrCode = GetSocketError(); + return AIE_RECEIVE_FAILED; + } + + // send the data to the filters + if( iFilter != NULL ) { + iFilter->ProcessIncomingData( iPacketBuffer, err ); + } + + // otherwise we have data to send to the datalink layer + derr = iProcessData->ProcessUUData( iPacketBuffer, err, &errcode ); + if( derr != DPE_NONE ) { + iLog->WriteLogEntry( SV_WARNING, "CUDPAirInterface::ListenOnInterface", "ProcessUUData returned", derr, errcode ); + } + } + + // code should never get here + assert( !"INVALID CODE PATH" ); + return AIE_NONE; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: MAIN-THREAD: StopInterface. Closes the socket (if it is open) + * was called. We can't guarantee when the receiving thread will return. But it + * must before any other calls can be made. + * + ******************************************************************************/ +int CUDPAirInterface::StopInterface() +{ + // set the exit flag + iExitFlag = 1; + + // close the socket if it is open + if( iSockIncoming != INVALID_SOCKET ) { + closesocket( iSockIncoming ); + iSockIncoming = iSockOutgoing = INVALID_SOCKET; + } + + // done + return 0; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: GetLocalAddress + * + ******************************************************************************/ +void CUDPAirInterface::GetLocalAddress( struct sockaddr_in *aLocalAddress ) +{ + assert( aLocalAddress != NULL ); + *aLocalAddress = iLocalAddress; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: SetRemoteAddress + * + ******************************************************************************/ +void CUDPAirInterface::GetRemoteAddress( struct sockaddr_in *aRemoteAddress ) +{ + *aRemoteAddress = iRemoteAddress; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: SetRemoteAddress + * + ******************************************************************************/ +void CUDPAirInterface::SetRemoteAddress( struct sockaddr_in aRemoteAddress ) +{ + iRemoteAddressValid = 1; + iRemoteAddress = aRemoteAddress; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: SetDatalink + * + ******************************************************************************/ +void CUDPAirInterface::SetDatalink( IProcessData *aProcessData ) +{ + iProcessData = aProcessData; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: RPC-THREAD. SetFilter, called by the main setup call in + * cphone - links up all the bits. + * + ******************************************************************************/ +void CUDPAirInterface::SetFilter( IFilter *aFilter ) +{ + iFilter = aFilter; +} + + +/******************************************************************************* + * + * PUBLIC METHOD: TE-THREAD: SendPacket, when data is received on the te + * channel it eventually makes its way here (in its thread) to send the + * data out the uu interface. + * + ******************************************************************************/ +TDataPathError CUDPAirInterface::SendPacket( char *data, int len, int *aErrCode ) +{ + int err; + + //verify the params + assert( data != NULL ); + assert( aErrCode != NULL ); + *aErrCode = 0; + + // make sure the remote address is set - not an error + if( iRemoteAddressValid == 0 ) { + return DPE_NONE; + } + + // send the packet - send in 4k chunks to avoid system defined UDP packet size limit + err = sendto( iSockOutgoing, data, len, 0, (struct sockaddr*)&iRemoteAddress, sizeof(iRemoteAddress) ); + if( err == SOCKET_ERROR ) { + *aErrCode = GetSocketError(); + return DPE_SEND_FAILED; + } + + // done + return DPE_NONE; +} + + +/******************************************************************************* + * + * PRIVATE METHODS: Helper functions + * + ******************************************************************************/ +int CUDPAirInterface::GetSocketError() +{ +#ifdef WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +}