testexecmgmt/ucc/Source/CSProtocolLibrary/sprotocol/CXServer.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 * Filename: CXServer.cpp
       
    16 * Author: Sanjeet Matharu 
       
    17 * This is the server side of the protocol which takes name/value pairs and does stuff
       
    18 * System Includes
       
    19 *
       
    20 */
       
    21 
       
    22 
       
    23 
       
    24 #include <stdio.h>
       
    25 #include <stdlib.h>
       
    26 #include <ctype.h>
       
    27 #include <memory.h>
       
    28 #include <string.h>
       
    29 #include <assert.h>
       
    30 
       
    31 #ifdef WIN32
       
    32 #include <winsock2.h>
       
    33 #include <windows.h>
       
    34 #else
       
    35 #include <sys/types.h>
       
    36 #include <sys/socket.h>
       
    37 #endif
       
    38 
       
    39 /*******************************************************************************
       
    40  *
       
    41  * Local Includes
       
    42  *
       
    43  ******************************************************************************/
       
    44 #include "cxserver.h"
       
    45 
       
    46 #define TIMEOUTPERIOD	15	//seconds
       
    47 
       
    48 //------------------------------------------------------------------------------
       
    49 //constructor
       
    50 CXServer::CXServer()
       
    51 {
       
    52 	iStatus = RECEIVE_HELLO;	//initialise to RECEIVE_HELLO
       
    53 
       
    54 	//initialise the name and value pairs
       
    55 	for(int i = 0; i < MAXLISTLENGTH; i++)
       
    56 	{
       
    57 		memset( iList[i].iName, 0, MAXBUFFERLEN );
       
    58 		memset( iList[i].iValue, 0, MAXBUFFERLEN );
       
    59 	}
       
    60 
       
    61 	iListPtr = NULL;					//this is used to point to either the name or the value in the list
       
    62 	timeout.tv_sec = TIMEOUTPERIOD;		//set up socket timeout period
       
    63 	timeout.tv_usec = 0;
       
    64 }
       
    65 
       
    66 //------------------------------------------------------------------------------
       
    67 //destructor
       
    68 CXServer::~CXServer()
       
    69 {
       
    70 	iStatus = RECEIVE_HELLO;	//end on RECEIVE_HELLO
       
    71 
       
    72 	iListPtr = NULL;
       
    73 	
       
    74 	//clear the name and value pairs
       
    75 	for(int i = 0; i < MAXLISTLENGTH; i++)
       
    76 	{
       
    77 		memset( iList[i].iName, 0, MAXBUFFERLEN );
       
    78 		memset( iList[i].iValue, 0, MAXBUFFERLEN );
       
    79 	}
       
    80 }
       
    81 
       
    82 //------------------------------------------------------------------------------
       
    83 //this function adds the specified value into the list of name value pairs
       
    84 int CXServer::OnExecute(int handle, int handletype)
       
    85 {
       
    86 	int err = 0;
       
    87 	int buff = -1;
       
    88 
       
    89 	//check the list for the next available space
       
    90 	for(int i = 0; i < MAXLISTLENGTH; i++ ) 
       
    91 	{
       
    92 		if( *iList[i].iName == 0 ) 
       
    93 		{
       
    94 			buff = i;
       
    95 			break;
       
    96 		}
       
    97 	}
       
    98 
       
    99 	// check that a slot was found, return error if not
       
   100 	if( buff == -1 ) 
       
   101 	{
       
   102 		return CSP_LISTFULL;
       
   103 	}
       
   104 
       
   105 	//if we get here and the status is value there is a problem and we'd loop like forever
       
   106 	while( iStatus != RECEIVE_VALUE )
       
   107 	{
       
   108 		switch( iStatus )
       
   109 		{
       
   110 			case RECEIVE_HELLO:
       
   111 				
       
   112 				err = CheckForHello(handle, handletype, buff);
       
   113 				
       
   114 				//the was a problem with the socket connection
       
   115 				if(err != 1)
       
   116 				{
       
   117 					return err;
       
   118 				}
       
   119 
       
   120 				break;
       
   121 	
       
   122 			case RECEIVE_NAME:
       
   123 
       
   124 				err = CheckForData(handle, handletype, buff);
       
   125 				
       
   126 				if(err != 0)
       
   127 				{
       
   128 					return err;
       
   129 				}
       
   130 				
       
   131 				break;
       
   132 
       
   133 			case RECEIVE_GOODBYE:
       
   134 
       
   135 				iStatus = RECEIVE_HELLO;
       
   136 				break;
       
   137 
       
   138 			default:
       
   139 
       
   140 				break;
       
   141 		}
       
   142 	}
       
   143 
       
   144 	// done
       
   145 	return err;
       
   146 }
       
   147 
       
   148 //------------------------------------------------------------------------------
       
   149 // This function checks to see whether the Hello call has been made by the client
       
   150 // it returns OK or ERROR accordingly
       
   151 int CXServer::CheckForHello(int handle, int handletype, int freeslot)
       
   152 {
       
   153 	char c;
       
   154 	int counter = 0;
       
   155 	int err;
       
   156 	int buff = -1;
       
   157 	int bufflen = 0;
       
   158 	
       
   159 	//initialisation
       
   160 	sprintf(&c, "%c", "");
       
   161 	sprintf(iHellobuffer, "%s", "HELLO");
       
   162 
       
   163 	//ensure that there are some free slots available in the list
       
   164 	assert(freeslot != -1);
       
   165 
       
   166 	buff = freeslot;
       
   167 
       
   168 	//set the pointer to point to the name element
       
   169 	iListPtr = iList[buff].iName;
       
   170 
       
   171 	while( 1 ) 
       
   172 	{
       
   173 		// receive the next byte
       
   174 		err = Read( handle, handletype, &c );
       
   175 				
       
   176 		//if something has been read from the socket
       
   177 		if( ( err == 1 ) )
       
   178 		{
       
   179 			//...and the character received is zero
       
   180 			if( strcmp( &c, "" ) == 0)
       
   181 			{
       
   182 				//we have the complete string so compare with our buffer
       
   183 				if(strcmp(iHellobuffer, iListPtr) != 0)
       
   184 				{
       
   185 					Write(handle, handletype, REPLY_ERROR, strlen(REPLY_ERROR) );
       
   186 					//clear the buffer
       
   187 					memset( iListPtr, 0, MAXBUFFERLEN );
       
   188 					//reset bufferlen counter so that writing can start from the beginning next time
       
   189 					bufflen = 0;
       
   190 				}
       
   191 				else	//data is ok
       
   192 				{
       
   193 					Write( handle, handletype, iListPtr, strlen(iListPtr) );
       
   194 					Write( handle, HT_SOCKET, "", 1 );
       
   195 					break;
       
   196 				}
       
   197 			}
       
   198 			else
       
   199 			{
       
   200 				// add the byte to the buffer
       
   201 				iListPtr[bufflen++] = c;
       
   202 			}
       
   203 		}
       
   204 		else	//if
       
   205 		{
       
   206 			//if there was a dodgy read then the socket link is broken
       
   207 			memset( iListPtr, 0, MAXBUFFERLEN );
       
   208 			bufflen = 0;
       
   209 			err = GetLastError();
       
   210 			printf( "Data could not be read.  Error code is %d...\n", err);
       
   211 			return err;
       
   212 		}
       
   213 	}	//while
       
   214 
       
   215 	//update the status
       
   216 	iStatus = RECEIVE_NAME;
       
   217 
       
   218 	//since the first element in the list will have HELLO in it, it should be reinitialised for use later on
       
   219 	memset( iListPtr, 0, MAXBUFFERLEN );
       
   220 	
       
   221 	return err;	
       
   222 }
       
   223 
       
   224 //------------------------------------------------------------------------------
       
   225 //this checks the socket for data
       
   226 int CXServer::CheckForData(int handle, int handletype, int freeslot)
       
   227 {
       
   228 	int bufflen = 0;
       
   229 	int buff = 0;
       
   230 	int err = 0;
       
   231 	char c;
       
   232 
       
   233 	assert( iStatus == RECEIVE_NAME);
       
   234 
       
   235 	buff = freeslot;
       
   236 
       
   237 	//check for data on the socket
       
   238 	if( CheckForTimeout(handle) != 0 )
       
   239 	{
       
   240 		//revert status to previous as we received no data within the alloted time
       
   241 		iStatus = RECEIVE_HELLO;
       
   242 		Write(handle, handletype, REPLY_TIMEOUT, strlen(REPLY_TIMEOUT) );
       
   243 		return err;
       
   244 	}
       
   245 
       
   246 	// the client should send the list of arguments - this is the name and value receiving section!!!!
       
   247 	// this section will continue to loop until the the goodbye message has been received
       
   248 	while( iStatus != RECEIVE_GOODBYE ) 
       
   249 	{
       
   250 		//need to do the timeout thing here for value data
       
   251 		if( iStatus == RECEIVE_VALUE )
       
   252 		{
       
   253 			if( CheckForTimeout(handle) != 0 )
       
   254 			{
       
   255 				//revert status to previous as we received no data within the alloted time
       
   256 				iStatus = RECEIVE_NAME;
       
   257 				//point to the previous name element in the array so that the last bit of data is overwritten
       
   258 				iListPtr = iList[buff].iName;
       
   259 				bufflen = 0;
       
   260 				Write( handle, handletype, REPLY_TIMEOUT, strlen(REPLY_TIMEOUT) );
       
   261 				return err;
       
   262 			}
       
   263 		}
       
   264 
       
   265 		// receive the next byte
       
   266 		err = Read( handle, handletype, &c );
       
   267 
       
   268 		//if something has been read from the socket
       
   269 		if( ( err == 1 ) )
       
   270 		{
       
   271 			//need to check for available data space
       
   272 			if( buff > (MAXLISTLENGTH - 1) ) 
       
   273 			{
       
   274 				Write(handle, handletype, REPLY_ERROR, strlen(REPLY_ERROR));
       
   275 				return 	CSP_LISTFULL;
       
   276 			}
       
   277 
       
   278 			// if the data buffer is full then we have an error
       
   279 			if( bufflen == (MAXBUFFERLEN - 1) ) 
       
   280 			{
       
   281 				Write(handle, handletype, REPLY_ERROR, strlen(REPLY_ERROR));
       
   282 				return 	CSP_BUFFERFULL;
       
   283 			}
       
   284 			
       
   285 			//...or the character received is zero		
       
   286 			if( strcmp( &c,"" ) == 0)
       
   287 			{
       
   288 				//reply to say that we got the data ok
       
   289 				Write( handle, handletype, iListPtr, strlen(iListPtr) );
       
   290 				Write( handle, HT_SOCKET, "", 1 );
       
   291 			
       
   292 				CheckForGoodbye(handle, handletype, buff);
       
   293 				
       
   294 				//if GOODBYE has not been received and the status has not changed
       
   295 				if( iStatus != RECEIVE_GOODBYE )
       
   296 				{
       
   297 					//change the status from name -> value or vice versa
       
   298 					if( iListPtr == iList[buff].iName )
       
   299 					{
       
   300 						iListPtr = iList[buff].iValue;
       
   301 						//reset bufferlen counter so that writing can start from the beginning
       
   302 
       
   303 						bufflen = 0;
       
   304 
       
   305 						iStatus = RECEIVE_VALUE;
       
   306 					}
       
   307 					else
       
   308 					{	
       
   309 						//move onto the next element in the list
       
   310 						iListPtr = iList[++buff].iName;
       
   311 						
       
   312 						//reset bufferlen counter so that writing can start from the beginning
       
   313 						bufflen = 0;
       
   314 						
       
   315 						iStatus = RECEIVE_NAME;
       
   316 					}		//else
       
   317 				}			//if (iStatus != ...)
       
   318 			}				//if (c == 0)
       
   319 			else
       
   320 			{
       
   321 				// add the byte to the buffer
       
   322 				iListPtr[bufflen++] = c;
       
   323 			}
       
   324 		}				//if
       
   325 		else
       
   326 		{
       
   327 			//if there was a dodgy read
       
   328 			Write(handle, handletype, REPLY_ERROR, strlen(REPLY_ERROR));
       
   329 			memset( iListPtr, 0, MAXBUFFERLEN );
       
   330 			
       
   331 			//reset bufferlen counter so that writing can start from the beginning next time
       
   332 			bufflen = 0;
       
   333 			
       
   334 			//and if status was VALUE then go back to NAME
       
   335 			if(iStatus = RECEIVE_VALUE)
       
   336 			{
       
   337 				iStatus = RECEIVE_NAME;
       
   338 				iListPtr = iList[buff].iName;
       
   339 				return err;
       
   340 			}
       
   341 		}
       
   342 	}
       
   343 
       
   344 	//change status back to receive hello
       
   345 	iStatus = RECEIVE_HELLO;
       
   346 
       
   347 	//everthing should be ok at this stage so reset err
       
   348 	err = 0;
       
   349 
       
   350 	return err;
       
   351 }
       
   352 
       
   353 //------------------------------------------------------------------------------
       
   354 //this function checks for the GOODBYE message.  If it has been set then it changes the status
       
   355 void CXServer::CheckForGoodbye(int handle, int handletype, int latestposition)
       
   356 {
       
   357 	
       
   358 	sprintf(iGoodbyebuffer, "%s", "GOODBYE");
       
   359 
       
   360 	//if an exact match is found
       
   361 	if(strcmp(iGoodbyebuffer, iListPtr) == 0)
       
   362 	{
       
   363 		//change status
       
   364 		iStatus = RECEIVE_GOODBYE;
       
   365 
       
   366 		//reset the data in the name/value slot
       
   367 		memset( iListPtr, 0, MAXBUFFERLEN );
       
   368 
       
   369 		printf( "Expecting HELLO from client side...\n" );
       
   370 	}
       
   371 }
       
   372 //------------------------------------------------------------------------------
       
   373 //this function reads data from a specific port
       
   374 int CXServer::Read(int handle, int handletype, char* c)
       
   375 {
       
   376 	int err = 0;
       
   377 
       
   378 	assert( c != NULL );
       
   379 	
       
   380 	// socket handles
       
   381 	if( handletype == HT_SOCKET ) 
       
   382 	{
       
   383 		err = recv( handle, c, 1, 0 );
       
   384 		if( err != 1 ) //if the single char has not been received
       
   385 		{
       
   386 			err = GetLastError();
       
   387 			return err;
       
   388 		}
       
   389 	}
       
   390 
       
   391 	return err;		
       
   392 }
       
   393 
       
   394 //------------------------------------------------------------------------------
       
   395 //this function writes on a specific port
       
   396 int CXServer::Write(int handle, int handletype, char *buff, int bufflen)
       
   397 {
       
   398 	int err;
       
   399 	
       
   400 	assert( buff != NULL );
       
   401 
       
   402 	// socket handles
       
   403 	if( handletype == HT_SOCKET ) 
       
   404 	{
       
   405 		err = send( handle, buff, bufflen, 0 );
       
   406 		if( err != bufflen ) 
       
   407 		{
       
   408 			err = GetLastError();
       
   409 			return err;
       
   410 		}
       
   411 	}
       
   412 
       
   413 	return 0;
       
   414 }
       
   415 
       
   416 //------------------------------------------------------------------------------
       
   417 //this function waits for input to be received on the specified socket for a specific time
       
   418 int CXServer::CheckForTimeout(int handle)
       
   419 {
       
   420 	int live = 0;
       
   421 	int err = 0;
       
   422 	
       
   423 	while( 1 )
       
   424 	{
       
   425 		//set up socket timer structure
       
   426 		FD_ZERO( &iReadSocketSet );
       
   427 		FD_SET( (unsigned)handle, &iReadSocketSet );
       
   428 
       
   429 		//wait for some input
       
   430 		live = select(NULL, &iReadSocketSet, NULL, NULL, &timeout);
       
   431 
       
   432 		//if there is some input
       
   433 		if( live < 0 )
       
   434 		{
       
   435 			printf( "Call to select() failed...\n" );
       
   436 			return live;
       
   437 		}
       
   438 		else if ( live == 0 )	
       
   439 		{
       
   440 			printf( "No descriptors ready...\n" );
       
   441 			printf( "Timed out...\n" );
       
   442 			err = -1;
       
   443 			return err;
       
   444 		}
       
   445 		else	//something is ready
       
   446 		{
       
   447 			FD_ISSET( handle, &iReadSocketSet );
       
   448 			printf( "Data read...\n" );
       
   449 			return err;
       
   450 		}
       
   451 	}
       
   452 
       
   453 	return err;
       
   454 }
       
   455 //------------------------------------------------------------------------------