diff -r 000000000000 -r 3da2a79470a7 testexecmgmt/ucc/Source/SerialTcpRelay/CSerialTcpRelay.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecmgmt/ucc/Source/SerialTcpRelay/CSerialTcpRelay.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,280 @@ +/* +* 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 + + +/************************************************************************************* + * + * LocalIncludes + * + ************************************************************************************/ +#include "CSerialTcpRelay.h" + + +/************************************************************************************* + * + * Definitions + * + ************************************************************************************/ +#define SOCKET_TIMEOUT (1000) + + +/************************************************************************************* + * + * PUBLIC METHOD: CSerialTcpRelay + * + ************************************************************************************/ +CSerialTcpRelay::CSerialTcpRelay() : iSerialThread("SerialThread"), iSocketThread("SocketThread") +{ + iSerialPort = NULL; + iSocket = INVALID_SOCKET; + iState = iSerialState = iSocketState = RS_NEW; +} + + +/************************************************************************************* + * + * PUBLIC METHOD: ~CSerialTcpRelay + * + ************************************************************************************/ +CSerialTcpRelay::~CSerialTcpRelay() +{ + assert( iSocket == INVALID_SOCKET ); + assert( iState != RS_ACTIVE ); + assert( iSerialState != RS_ACTIVE ); + assert( iSocketState != RS_ACTIVE ); +} + + +/************************************************************************************* + * + * PUBLIC METHOD: InitialiseRelay + * + ************************************************************************************/ +TRelayError CSerialTcpRelay::InitialiseRelay( CSerialPort *aSerialPort, SOCKADDR_IN aRemoteAddress, char *aInitialBuffer, int aBufferLength, int *aErrCode ) +{ + int err; + + // check params + assert( aSerialPort != NULL ); + assert( aErrCode != NULL ); + + // save the state vars + *aErrCode = 0; + iSerialPort = aSerialPort; + iRemoteAddress = aRemoteAddress; + + // open the socket + iSocket = socket( AF_INET, SOCK_STREAM, 0 ); + if( iSocket == INVALID_SOCKET ){ + *aErrCode = WSAGetLastError(); + return RE_SOCKET_FAILED; + } + err = connect( iSocket, (struct sockaddr*)&iRemoteAddress, sizeof(iRemoteAddress) ); + if( err == SOCKET_ERROR ) { + *aErrCode = WSAGetLastError(); + closesocket( iSocket ); + iSocket = INVALID_SOCKET; + return RE_CONNECT_FAILED; + } + + // if there is some initial data then send it + if( (aInitialBuffer != NULL) && (aBufferLength > 0) ) { + err = send( iSocket, aInitialBuffer, aBufferLength, 0 ); + if( err != aBufferLength ) { + *aErrCode = WSAGetLastError(); + closesocket( iSocket ); + iSocket = INVALID_SOCKET; + return RE_INITIAL_SEND_FAILED; + } + } + + // update the state + iState = iSerialState = iSocketState = RS_ACTIVE; + + // ok we are ready to go + return RE_SUCCESS; +} + + +/************************************************************************************* + * + * PUBLIC METHOD: ExecuteRelay + * + ************************************************************************************/ +TRelayError CSerialTcpRelay::ExecuteRelay() +{ + TThreadError terr; + int errcode; + + // create the serial thread + terr = iSerialThread.StartThread( CSerialTcpRelay::SerialThreadProc, this, &errcode ); + assert( terr == TE_NONE ); + + // create the socket thread + terr = iSocketThread.StartThread( CSerialTcpRelay::SocketThreadProc, this, &errcode ); + assert( terr == TE_NONE ); + + // wait for the serial thread to exit + terr = iSerialThread.WaitForThread( INFINITE ); + assert( terr == TE_NONE ); + + // wait for the socket thread to exit + terr = iSocketThread.WaitForThread( INFINITE ); + assert( terr == TE_NONE ); + + // done + iState = RS_CLOSED; + return RE_SUCCESS; +} + + +/************************************************************************************* + * + * PRIVATE METHOD: ExecuteSerialThread + * + ************************************************************************************/ +TRelayError CSerialTcpRelay::ExecuteSerialThread() +{ + int err, bytes_read; + DWORD dwModemStatus; + + // repeat... + while( 1 ) { + + // read from the serial port + bytes_read = SERIALREADBUFFSIZE; + err = iSerialPort->ReceiveBytes( iSerialReadBuffer, &bytes_read ); + + // if there was an error other than timeout then break + if( err != 0 ) { + break; + } + + // write any received data to the socket - break on error + if( bytes_read > 0 ) { +// fprintf( stderr, "DEBUG: serial <-> socket (%d)\n", bytes_read ); + err = send( iSocket, iSerialReadBuffer, bytes_read, 0 ); + if( err != bytes_read ) { + break; + } + } + + // check the serial line flags - if the peer has lowered cts or dsr then + // we take this as meaning that they have closed the port + err = GetCommModemStatus( iSerialPort->Handle(), &dwModemStatus ); + assert( err != 0 ); + if( ((dwModemStatus & MS_CTS_ON) == 0) ) { + break; + } + + // if the socket thread has exited then exit + if( iSocketState == RS_CLOSED ) { + break; + } + } + + // set my status to closed + iSerialState = RS_CLOSED; + return RE_SUCCESS; +} + + +/************************************************************************************* + * + * PRIVATE METHOD: ExecuteSerialThread + * + ************************************************************************************/ +TRelayError CSerialTcpRelay::ExecuteSocketThread() +{ + int err, bytes_read, bytes_written; + struct timeval read_timeout; + fd_set read_fds; + + // repeat... + while( 1 ) { + + // setup things + read_timeout.tv_sec = 0; + read_timeout.tv_usec = (SOCKET_TIMEOUT*1000); + FD_ZERO( &read_fds ); + FD_SET( iSocket, &read_fds ); + + // see if data is available + err = select( 1, &read_fds, NULL, NULL, &read_timeout ); + + // break on errors + if( err == SOCKET_ERROR ) { + break; + } + + // if there is data available then read it - break on error + if( err != 0 ) { + bytes_read = recv( iSocket, iSocketReadBuffer, SOCKETREADBUFFSIZE, 0 ); + if( bytes_read <= 0 ) { + break; + } + } + + // write any received data to the serial port - break on error + if( bytes_read > 0 ) { + bytes_written = bytes_read; +// fprintf( stderr, "DEBUG: socket <-> serial (%d)\n", bytes_read ); + err = iSerialPort->SendBytes( iSocketReadBuffer, &bytes_written ); + if( err != 0 ) { + break; + } + } + + // if the serial thread has exited then exit + if( iSerialState == RS_CLOSED ) { + break; + } + + } + + // close the socket + closesocket( iSocket ); + iSocket = INVALID_SOCKET; + + // set my status to closed + iSocketState = RS_CLOSED; + return RE_SUCCESS; +} + + +/************************************************************************************* + * + * PRIVATE METHOD: Thread Entry Procs + * + ************************************************************************************/ +int CSerialTcpRelay::SerialThreadProc( CSerialTcpRelay *aRelay ) +{ + return (int)aRelay->ExecuteSerialThread(); +} + + +int CSerialTcpRelay::SocketThreadProc( CSerialTcpRelay *aRelay ) +{ + return (int)aRelay->ExecuteSocketThread(); +} +