testexecmgmt/ucc/Source/SerialTcpRelay/CSerialTcpRelay.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * System Includes
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include <stdio.h>
       
    22 #include <assert.h>
       
    23 
       
    24 
       
    25 /*************************************************************************************
       
    26  *
       
    27  * LocalIncludes
       
    28  *
       
    29  ************************************************************************************/
       
    30 #include "CSerialTcpRelay.h"
       
    31 
       
    32 
       
    33 /*************************************************************************************
       
    34  *
       
    35  * Definitions
       
    36  *
       
    37  ************************************************************************************/
       
    38 #define SOCKET_TIMEOUT (1000)
       
    39 
       
    40 
       
    41 /*************************************************************************************
       
    42  *
       
    43  * PUBLIC METHOD: CSerialTcpRelay
       
    44  *
       
    45  ************************************************************************************/
       
    46 CSerialTcpRelay::CSerialTcpRelay() : iSerialThread("SerialThread"), iSocketThread("SocketThread")
       
    47 {
       
    48 	iSerialPort = NULL;
       
    49 	iSocket = INVALID_SOCKET;
       
    50 	iState = iSerialState = iSocketState = RS_NEW;
       
    51 }
       
    52 
       
    53 
       
    54 /*************************************************************************************
       
    55  *
       
    56  * PUBLIC METHOD: ~CSerialTcpRelay
       
    57  *
       
    58  ************************************************************************************/
       
    59 CSerialTcpRelay::~CSerialTcpRelay()
       
    60 {
       
    61 	assert( iSocket == INVALID_SOCKET );
       
    62 	assert( iState != RS_ACTIVE );
       
    63 	assert( iSerialState != RS_ACTIVE );
       
    64 	assert( iSocketState != RS_ACTIVE );
       
    65 }
       
    66 
       
    67 
       
    68 /*************************************************************************************
       
    69  *
       
    70  * PUBLIC METHOD: InitialiseRelay
       
    71  *
       
    72  ************************************************************************************/
       
    73 TRelayError CSerialTcpRelay::InitialiseRelay( CSerialPort *aSerialPort, SOCKADDR_IN aRemoteAddress, char *aInitialBuffer, int aBufferLength, int *aErrCode )
       
    74 {
       
    75 	int err;
       
    76 
       
    77 	// check params
       
    78 	assert( aSerialPort != NULL );
       
    79 	assert( aErrCode != NULL );
       
    80 
       
    81 	// save the state vars
       
    82 	*aErrCode = 0;
       
    83 	iSerialPort = aSerialPort;
       
    84 	iRemoteAddress = aRemoteAddress;
       
    85 
       
    86 	// open the socket
       
    87 	iSocket = socket( AF_INET, SOCK_STREAM, 0 );
       
    88 	if( iSocket == INVALID_SOCKET ){
       
    89 		*aErrCode = WSAGetLastError();
       
    90 		return RE_SOCKET_FAILED;
       
    91 	}
       
    92 	err = connect( iSocket, (struct sockaddr*)&iRemoteAddress, sizeof(iRemoteAddress) );
       
    93 	if( err == SOCKET_ERROR ) {
       
    94 		*aErrCode = WSAGetLastError();
       
    95 		closesocket( iSocket );
       
    96 		iSocket = INVALID_SOCKET;
       
    97 		return RE_CONNECT_FAILED;
       
    98 	}
       
    99 
       
   100 	// if there is some initial data then send it
       
   101 	if( (aInitialBuffer != NULL) && (aBufferLength > 0) ) {
       
   102 		err = send( iSocket, aInitialBuffer, aBufferLength, 0 );
       
   103 		if( err != aBufferLength ) {
       
   104 			*aErrCode = WSAGetLastError();
       
   105 			closesocket( iSocket );
       
   106 			iSocket = INVALID_SOCKET;
       
   107 			return RE_INITIAL_SEND_FAILED;
       
   108 		}
       
   109 	}
       
   110 
       
   111 	// update the state
       
   112 	iState = iSerialState = iSocketState = RS_ACTIVE;
       
   113 
       
   114 	// ok we are ready to go
       
   115 	return RE_SUCCESS;
       
   116 }
       
   117 
       
   118 
       
   119 /*************************************************************************************
       
   120  *
       
   121  * PUBLIC METHOD: ExecuteRelay
       
   122  *
       
   123  ************************************************************************************/
       
   124 TRelayError CSerialTcpRelay::ExecuteRelay()
       
   125 {
       
   126 	TThreadError terr;
       
   127 	int errcode;
       
   128 
       
   129 	// create the serial thread
       
   130 	terr = iSerialThread.StartThread( CSerialTcpRelay::SerialThreadProc, this, &errcode );
       
   131 	assert( terr == TE_NONE );
       
   132 
       
   133 	// create the socket thread
       
   134 	terr = iSocketThread.StartThread( CSerialTcpRelay::SocketThreadProc, this, &errcode );
       
   135 	assert( terr == TE_NONE );
       
   136 
       
   137 	// wait for the serial thread to exit
       
   138 	terr = iSerialThread.WaitForThread( INFINITE );
       
   139 	assert( terr == TE_NONE );
       
   140 
       
   141 	// wait for the socket thread to exit
       
   142 	terr = iSocketThread.WaitForThread( INFINITE );
       
   143 	assert( terr == TE_NONE );
       
   144 
       
   145 	// done
       
   146 	iState = RS_CLOSED;
       
   147 	return RE_SUCCESS;
       
   148 }
       
   149 
       
   150 
       
   151 /*************************************************************************************
       
   152  *
       
   153  * PRIVATE METHOD: ExecuteSerialThread
       
   154  *
       
   155  ************************************************************************************/
       
   156 TRelayError CSerialTcpRelay::ExecuteSerialThread()
       
   157 {
       
   158 	int err, bytes_read;
       
   159 	DWORD dwModemStatus;
       
   160 
       
   161 	// repeat...
       
   162 	while( 1 ) {
       
   163 
       
   164 		// read from the serial port
       
   165 		bytes_read = SERIALREADBUFFSIZE;
       
   166 		err = iSerialPort->ReceiveBytes( iSerialReadBuffer, &bytes_read );
       
   167 
       
   168 		// if there was an error other than timeout then break
       
   169 		if( err != 0 ) {
       
   170 			break;
       
   171 		}
       
   172 
       
   173 		// write any received data to the socket - break on error
       
   174 		if( bytes_read > 0 ) {
       
   175 //			fprintf( stderr, "DEBUG: serial <-> socket (%d)\n", bytes_read );
       
   176 			err = send( iSocket, iSerialReadBuffer, bytes_read, 0 );
       
   177 			if( err != bytes_read ) {
       
   178 				break;
       
   179 			}
       
   180 		}
       
   181 
       
   182 		// check the serial line flags - if the peer has lowered cts or dsr then
       
   183 		// we take this as meaning that they have closed the port
       
   184 		err = GetCommModemStatus( iSerialPort->Handle(), &dwModemStatus );
       
   185 		assert( err != 0 );
       
   186 		if( ((dwModemStatus & MS_CTS_ON) == 0) ) {
       
   187 			break;
       
   188 		}
       
   189 
       
   190 		// if the socket thread has exited then exit
       
   191 		if( iSocketState == RS_CLOSED ) {
       
   192 			break;
       
   193 		}
       
   194 	}
       
   195 		
       
   196 	// set my status to closed 
       
   197 	iSerialState = RS_CLOSED;
       
   198 	return RE_SUCCESS;
       
   199 }
       
   200 
       
   201 
       
   202 /*************************************************************************************
       
   203  *
       
   204  * PRIVATE METHOD: ExecuteSerialThread
       
   205  *
       
   206  ************************************************************************************/
       
   207 TRelayError CSerialTcpRelay::ExecuteSocketThread()
       
   208 {
       
   209 	int err, bytes_read, bytes_written;
       
   210 	struct timeval read_timeout;
       
   211 	fd_set read_fds;
       
   212 
       
   213 	// repeat...
       
   214 	while( 1 ) {
       
   215 
       
   216 		// setup things
       
   217 		read_timeout.tv_sec = 0;
       
   218 		read_timeout.tv_usec = (SOCKET_TIMEOUT*1000);
       
   219 		FD_ZERO( &read_fds );
       
   220 		FD_SET( iSocket, &read_fds );
       
   221 
       
   222 		// see if data is available
       
   223 		err = select( 1, &read_fds, NULL, NULL, &read_timeout );
       
   224 
       
   225 		// break on errors
       
   226 		if( err == SOCKET_ERROR ) {
       
   227 			break;
       
   228 		}
       
   229 
       
   230 		// if there is data available then read it - break on error
       
   231 		if( err != 0 ) {
       
   232 			bytes_read = recv( iSocket, iSocketReadBuffer, SOCKETREADBUFFSIZE, 0 );
       
   233 			if( bytes_read <= 0 ) {
       
   234 				break;
       
   235 			}
       
   236 		}
       
   237 
       
   238 		// write any received data to the serial port - break on error
       
   239 		if( bytes_read > 0 ) {
       
   240 			bytes_written = bytes_read;
       
   241 //			fprintf( stderr, "DEBUG: socket <-> serial (%d)\n", bytes_read );
       
   242 			err = iSerialPort->SendBytes( iSocketReadBuffer, &bytes_written );
       
   243 			if( err != 0 ) {
       
   244 				break;
       
   245 			}
       
   246 		}
       
   247 
       
   248 		// if the serial thread has exited then exit
       
   249 		if( iSerialState == RS_CLOSED ) {
       
   250 			break;
       
   251 		}
       
   252 
       
   253 	}
       
   254 	
       
   255 	// close the socket
       
   256 	closesocket( iSocket );
       
   257 	iSocket = INVALID_SOCKET;
       
   258 
       
   259 	// set my status to closed 
       
   260 	iSocketState = RS_CLOSED;
       
   261 	return RE_SUCCESS;
       
   262 }
       
   263 
       
   264 
       
   265 /*************************************************************************************
       
   266  *
       
   267  * PRIVATE METHOD: Thread Entry Procs
       
   268  *
       
   269  ************************************************************************************/
       
   270 int CSerialTcpRelay::SerialThreadProc( CSerialTcpRelay *aRelay )
       
   271 {
       
   272 	return (int)aRelay->ExecuteSerialThread();
       
   273 }
       
   274 
       
   275 
       
   276 int CSerialTcpRelay::SocketThreadProc( CSerialTcpRelay *aRelay )
       
   277 {
       
   278 	return (int)aRelay->ExecuteSocketThread();
       
   279 }
       
   280