Home | History | Annotate | Download | only in CLI
      1 /*******************************************************************************
      2 **+--------------------------------------------------------------------------+**
      3 **|                                                                          |**
      4 **| Copyright 1998-2008 Texas Instruments, Inc. - http://www.ti.com/         |**
      5 **|                                                                          |**
      6 **| Licensed under the Apache License, Version 2.0 (the "License");          |**
      7 **| you may not use this file except in compliance with the License.         |**
      8 **| You may obtain a copy of the License at                                  |**
      9 **|                                                                          |**
     10 **|     http://www.apache.org/licenses/LICENSE-2.0                           |**
     11 **|                                                                          |**
     12 **| Unless required by applicable law or agreed to in writing, software      |**
     13 **| distributed under the License is distributed on an "AS IS" BASIS,        |**
     14 **| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |**
     15 **| See the License for the specific language governing permissions and      |**
     16 **| limitations under the License.                                           |**
     17 **|                                                                          |**
     18 **+--------------------------------------------------------------------------+**
     19 *******************************************************************************/
     20 
     21 /****************************************************************************************************/
     22 /*                                                                                                  */
     23 /*      MODULE:     eth_utils.c                                                                     */
     24 /*      PURPOSE:    Ethernet communication utilities                                                */
     25 /*                                                                                                  */
     26 /****************************************************************************************************/
     27 
     28 #include <sys/types.h>
     29 #include <sys/socket.h>
     30 #include <sys/select.h>
     31 #include <unistd.h>
     32 #include <arpa/inet.h>
     33 
     34 #include "ipc.h"
     35 #include "ticon.h"
     36 #include "errno.h"
     37 #include "signal.h"
     38 #include "eth_utils.h"
     39 
     40 extern char* inet_ntoa(struct  in_addr);
     41 	/************/
     42 	/* Defines */
     43 	/**********/
     44 
     45 #define LOOGER_ETHERNET_PORT	(700)
     46 #define WIPP_ETHERNET_PORT		(701)
     47 #define G_TESTER_ETHERNET_PORT	(702)
     48 
     49 #define READ_STATE_GET_HEADER		(0x00)
     50 #define READ_STATE_GET_LENGTH1		(0x01)
     51 #define READ_STATE_GET_LENGTH2		(0x02)
     52 #define READ_STATE_GET_PAYLOAD		(0x03)
     53 
     54 #define PACKET_PREFIX			(0xFF)
     55 
     56 #define IN_BUFFER_SIZE			(1024)
     57 #define OUT_BUFFER_SIZE			(512)
     58 
     59 	/*********************/
     60 	/* Global variables */
     61 	/*******************/
     62 
     63 unsigned char ethernet_utils_welcome_message[] = {'W', 2, 0, 2, ETH_UTILS_PROTOCOL_VERSION};
     64 
     65 char ethernet_utils_module_names[ETHERNET_UTILS_NUMBER_OF_MODULES][20] =
     66 {
     67 	"terminal",
     68 	"logger",
     69 	"wipp control",
     70 	"g tester"
     71 };
     72 
     73 	/********************************/
     74 	/* static functions prototypes */
     75 	/******************************/
     76 
     77 int ethernet_utils_init_module(int module_index, u_short port_number, int *module_pipe, unsigned char mux_uart_id);
     78 void ethernet_utils_signal_handler(int signal);
     79 int ethernet_utils_process_in_command(int module_index, unsigned char *read_state, unsigned short *packet_size, unsigned char *in_buffer, unsigned int *in_buffer_offset);
     80 int ethernet_utils_write_socket(int module_index, int length, unsigned char *buffer);
     81 void ethernet_utils_disconnect_socket(int module_index);
     82 
     83 	/**************/
     84 	/* Functions */
     85 	/************/
     86 
     87 /************************************************************************
     88  *                        ethernet_utils_init                           *
     89  ************************************************************************
     90 DESCRIPTION: Initialize the ethernet communication
     91 
     92 CONTEXT	   : main process only!
     93 ************************************************************************/
     94 void ethernet_utils_init()
     95 {
     96 	ethernet_logger_process_pid = ethernet_utils_init_module(ETHERNET_UTILS_LOGGER_MODULE_ID, LOOGER_ETHERNET_PORT, ethernet_logger_pipe, LOGGER_MUX_UART_ID);
     97 	ethernet_wipp_process_pid = ethernet_utils_init_module(ETHERNET_UTILS_WIPP_MODULE_ID, WIPP_ETHERNET_PORT, ethernet_wipp_control_pipe, WIPP_CONTROL_MUX_UART_ID);
     98 	ethernet_g_tester_process_pid = ethernet_utils_init_module(ETHERNET_UTILS_G_TESTER_MODULE_ID, G_TESTER_ETHERNET_PORT, ethernet_g_tester_pipe, G_TESTER_MUX_UART_ID);
     99 }
    100 
    101 /************************************************************************
    102  *                        ethernet_utils_deinit                         *
    103  ************************************************************************
    104 DESCRIPTION: Deinitialize the ethernet communication
    105 
    106 CONTEXT	   : main process only!
    107 ************************************************************************/
    108 void ethernet_utils_deinit()
    109 {
    110 	/* Kill the logger process */
    111 	if (ethernet_logger_process_pid > 0)
    112 	{
    113 		kill(ethernet_logger_process_pid, SIGKILL);
    114 	}
    115 
    116 	/* Kill the wipp control process */
    117 	if (ethernet_wipp_process_pid > 0)
    118 	{
    119 		kill(ethernet_wipp_process_pid, SIGKILL);
    120 	}
    121 
    122 	/* Kill the wipp control process */
    123 	if (ethernet_g_tester_process_pid > 0)
    124 	{
    125 		kill(ethernet_g_tester_process_pid, SIGKILL);
    126 	}
    127 }
    128 
    129 /************************************************************************
    130  *                        ethernet_utils_signal_handler                 *
    131  ************************************************************************
    132 DESCRIPTION: Signal handler - receive the USER
    133 
    134 CONTEXT	   : Signal owner
    135 ************************************************************************/
    136 void ethernet_utils_signal_handler(int signal)
    137 {
    138 }
    139 
    140 /************************************************************************
    141  *                        ethernet_utils_init_module                    *
    142  ************************************************************************
    143 DESCRIPTION: Initialize ethernet communication
    144 
    145 RETURNS:   : Process ID of the new process or -1 if error.
    146 
    147 CONTEXT	   : main process only!
    148 ************************************************************************/
    149 int ethernet_utils_init_module(int module_index, u_short port_number, int *module_pipe, unsigned char mux_uart_id)
    150 {
    151 	int child_process_id;
    152 
    153 	/***************************************/
    154 	/* Create a pipe to control the child */
    155 	/*************************************/
    156 
    157 	if (pipe(module_pipe) < 0)
    158 	{
    159 		console_printf_terminal("eth_utils, error creating pipe\n");
    160 
    161 		return -1;
    162 	}
    163 
    164 	/* Set the shared memory variables */
    165 	SHARED_MEMORY_IPC_PIPE(module_index) = module_pipe[1];
    166 	SHARED_MEMORY_MUX_UART_ID(module_index) = mux_uart_id;
    167 
    168 	/* Create a child process */
    169 	child_process_id = fork();
    170 
    171 	if (0 == child_process_id)
    172 	{
    173 		/******************/
    174 		/* Child process */
    175 		/****************/
    176 
    177 		int result;
    178 		int socket_id;
    179 		int optval = 1;
    180 		int socket_alive;
    181 		int max_fd_index;
    182 		socklen_t client_addr_len;
    183 		fd_set read_set;
    184 		unsigned char out_buffer[OUT_BUFFER_SIZE];
    185 		unsigned char in_buffer[IN_BUFFER_SIZE];
    186 		unsigned char read_state;
    187 		unsigned short packet_size;
    188 		unsigned int in_buffer_offset;
    189 		struct sockaddr_in server_addr;
    190 		struct sockaddr_in client_addr;
    191 
    192 		console_printf_terminal("eth_utils, Hello from %s child module (pid = %d).\n", ethernet_utils_module_names[module_index], getpid());
    193 
    194 		/* Close the write direction of the pipe  - because i only read information from this pipe. */
    195 		close(module_pipe[1]);
    196 
    197 		SHARED_MEMORY_OUTPUT_PATH(module_index) = OUTPUT_PATH_SIMPLE_UART;
    198 
    199 		/* Set the signal handler for the 'SIGUSR1' signal */
    200 		signal(SIGUSR1, ethernet_utils_signal_handler);
    201 
    202 		while (TRUE)
    203 		{
    204 			/******************/
    205 			/* Open a socket */
    206 			/****************/
    207 
    208 			socket_id = socket(PF_INET, SOCK_STREAM, 0);
    209 
    210 			if (!socket_id)
    211 			{
    212 				/* Error opening socket */
    213 
    214 				console_printf_terminal("eth_utils, error opening %s socket. (errno = %d)\n", ethernet_utils_module_names[module_index], errno);
    215 
    216 				_exit(1);
    217 			}
    218 
    219 			/*************************/
    220 			/* Configure the socket */
    221 			/***********************/
    222 
    223 			if (setsockopt(socket_id, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
    224 			{
    225 				/* Error setting socket option */
    226 
    227 				console_printf_terminal("eth_utils, error setting %s socket option.  (errno = %d)\n", ethernet_utils_module_names[module_index], errno);
    228 
    229 				_exit(1);
    230 			}
    231 
    232 			/********************/
    233 			/* Bind the socket */
    234 			/******************/
    235 
    236 			server_addr.sin_family = AF_INET;
    237 			server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
    238 			server_addr.sin_port = htons(port_number);
    239 
    240 			result = bind(socket_id, (struct sockaddr *)&server_addr, sizeof(server_addr));
    241 
    242 			if (result != 0)
    243 			{
    244 				/* Error binding socket */
    245 
    246 				console_printf_terminal("eth_utils, error binding %s socket. (errno = %d)\n", ethernet_utils_module_names[module_index], errno);
    247 
    248 				_exit(1);
    249 			}
    250 
    251 			/****************************/
    252 			/* Listening to the socket */
    253 			/**************************/
    254 
    255 			result = listen(socket_id, 5);
    256 
    257 			if (-1 == result)
    258 			{
    259 				/* Error listening to socket */
    260 
    261 				console_printf_terminal("eth_utils, error listening to %s socket. (errno = %d)\n", ethernet_utils_module_names[module_index], errno);
    262 
    263 				_exit(1);
    264 			}
    265 
    266 			/**********************/
    267 			/* Accept connection */
    268 			/********************/
    269 
    270 			client_addr_len = sizeof(client_addr);
    271 
    272 			/* We suppose to get new socket id after accept (blocking action) */
    273 			result = accept(socket_id, (struct sockaddr *)&client_addr, &client_addr_len);
    274 
    275 			if (-1 == result)
    276 			{
    277 				/* Error accepting connection */
    278 
    279 				console_printf_terminal("eth_utils, error accepting %s connection. (errno = %d)\n", ethernet_utils_module_names[module_index], errno);
    280 
    281 				_exit(1);
    282 			}
    283 
    284 			close(socket_id);
    285 
    286 			socket_id = result;
    287 
    288 			read_state = READ_STATE_GET_HEADER;
    289 
    290 			SHARED_MEMORY_ETHERNET_SOCKET_ID(module_index) = socket_id;
    291 
    292 			console_printf_terminal("\n***********************************************\n");
    293 			console_printf_terminal("* eth_utils, %s connection accepted. \n", ethernet_utils_module_names[module_index]);
    294 			console_printf_terminal("*\n* Remote IP: %s\n***********************************************\n", inet_ntoa(client_addr.sin_addr));
    295 
    296 			/* Switch to ethernet output */
    297 			SHARED_MEMORY_OUTPUT_PATH(module_index) = OUTPUT_PATH_ETHERNET;
    298 
    299 			/*********************************/
    300 			/* Send Hello message to client */
    301 			/*******************************/
    302 
    303 			ethernet_utils_write_socket(module_index, sizeof(ethernet_utils_welcome_message), ethernet_utils_welcome_message);
    304 
    305 			/**********************/
    306 			/* Manage connection */
    307 			/********************/
    308 
    309 			socket_alive = TRUE;
    310 
    311 			while (socket_alive)
    312 			{
    313 				/***********************************************************************************/
    314 				/* Wait for one of two external events: 									      */
    315 				/* -----------------------------------											 */
    316 				/*																			    */
    317 				/* 1. Data received from TCP client and should be transfered to parent process */
    318 				/* 2. Data received from parent process and should be transfered to client 	  */
    319 				/*****************************************************************************/
    320 
    321 				/* Prepare the read set fields */
    322 				FD_ZERO(&read_set);
    323 				FD_SET(socket_id, &read_set);
    324 				FD_SET(module_pipe[0], &read_set);
    325 
    326 				/* Determine the maximum index of the file descriptor */
    327 				max_fd_index = (max(socket_id, module_pipe[0]) + 1);
    328 
    329 				/* Wait for event - blocking */
    330 				result = select(max_fd_index, &read_set, NULL, NULL, NULL);
    331 
    332 				/************************/
    333 				/* Check event results */
    334 				/**********************/
    335 
    336 				if (result > 0)
    337 				{
    338 					if (FD_ISSET(socket_id, &read_set))
    339 					{
    340 						/******************************/
    341 						/* Data received from client */
    342 						/****************************/
    343 
    344 						/* Process the input command */
    345 						if (ethernet_utils_process_in_command(module_index, &read_state, &packet_size, in_buffer, &in_buffer_offset) <= 0)
    346 						{
    347 							socket_alive = FALSE;
    348 						}
    349 					}
    350 
    351 					if (FD_ISSET(module_pipe[0], &read_set))
    352                     {
    353 						/**************************************/
    354 						/* Data received from parent process */
    355 						/************************************/
    356 
    357 						result = read(module_pipe[0], out_buffer, sizeof(out_buffer));
    358                         if( result < 0 )
    359                         {
    360                             console_printf_terminal("eth_utils, read error (err=%d)\n", result);
    361                             socket_alive = FALSE;
    362                         }
    363 
    364 						if (ethernet_utils_write_socket(module_index, result, out_buffer) == -1)
    365 						{
    366 							socket_alive = FALSE;
    367 						}
    368 					}
    369 				}
    370 				else
    371 				{
    372 					console_printf_terminal("eth_utils, 'select' command error\n");
    373 
    374 					socket_alive = FALSE;
    375 				}
    376 			}
    377 
    378 			/* Disconnect the socket */
    379 			ethernet_utils_disconnect_socket(module_index);
    380 		}
    381 	}
    382 
    383 	/* Close the read direction of the pipe  - because i only write information from this pipe. (to child process) */
    384 	close(module_pipe[0]);
    385 
    386 	/* return the process id, I will use it later when i want to kill this process */
    387 	return child_process_id;
    388 }
    389 
    390 /************************************************************************
    391  *                        ethernet_utils_process_in_command             *
    392  ************************************************************************
    393 DESCRIPTION: Handle In commands
    394 
    395 CONTEXT	   : Only the same process that is reading from the socket
    396 ************************************************************************/
    397 int ethernet_utils_process_in_command(int module_index, unsigned char *read_state, unsigned short *packet_size, unsigned char *in_buffer, unsigned int *in_buffer_offset)
    398 {
    399 	unsigned char prefix;
    400 	int socket_id = SHARED_MEMORY_ETHERNET_SOCKET_ID(module_index);
    401     int result = 1;
    402 
    403 	/*console_printf_terminal("ethernet_utils_process_in_command (socket = %d)\n", socket_id); */
    404 
    405 	/* Continue while there is data in the RX buffer */
    406 	switch (*read_state)
    407 	{
    408 	case READ_STATE_GET_HEADER:
    409 
    410 		/* Read the packet prefix - one byte */
    411 		result = read(socket_id, &prefix, sizeof(prefix));
    412 		/*console_printf_terminal("ethernet_utils_process_in_command (State = READ_STATE_GET_HEADER, length = %d)\n", result); */
    413 
    414 		if (result > 0)
    415 		{
    416 			if (prefix == PACKET_PREFIX)
    417 			{
    418 				*read_state = READ_STATE_GET_LENGTH1;
    419 			}
    420 			else
    421 			{
    422 				console_printf_terminal("ethernet_utils_process_in_command, Error: protocol sync error! \n");
    423 
    424 				result = -1;
    425 			}
    426 		}
    427 
    428 		break;
    429 
    430 	case READ_STATE_GET_LENGTH1:
    431 
    432 		/* Read the packet size first byte */
    433 		result = read(socket_id, (void *)((unsigned char *)(packet_size) + 0), sizeof(unsigned char));
    434 		/*console_printf_terminal("ethernet_utils_process_in_command (State = READ_STATE_GET_LENGTH1, length = %d)\n", result); */
    435 
    436 		if (result > 0)
    437 		{
    438 			*read_state = READ_STATE_GET_LENGTH2;
    439 		}
    440 
    441 		break;
    442 
    443 	case READ_STATE_GET_LENGTH2:
    444 
    445 		/* Read the packet size second byte */
    446 		result = read(socket_id, (void *)((unsigned char *)(packet_size) + 1), sizeof(unsigned char));
    447 		/*console_printf_terminal("ethernet_utils_process_in_command (State = READ_STATE_GET_LENGTH2, length = %d, packet_size = %d)\n", result, *packet_size); */
    448 
    449 		if (result > 0)
    450 		{
    451 			/* Sanity check on the length */
    452 
    453 			*in_buffer_offset = 0;
    454 
    455 			*read_state = READ_STATE_GET_PAYLOAD;
    456 		}
    457 
    458 		break;
    459 
    460 
    461 	case READ_STATE_GET_PAYLOAD:
    462 
    463 		/* Read the packet size second byte */
    464 		result = read(socket_id, (in_buffer + 3 + *in_buffer_offset), (*packet_size - *in_buffer_offset));
    465 		/*console_printf_terminal("ethernet_utils_process_in_command (State = READ_STATE_GET_PAYLOAD, offset = %d, length = %d)\n", *in_buffer_offset, result); */
    466 
    467 		if (result > 0)
    468 		{
    469 			*in_buffer_offset += result;
    470 
    471 			if (*packet_size == *in_buffer_offset)
    472 			{
    473 				/* All the packet has arrived */
    474 
    475 				*read_state = READ_STATE_GET_HEADER;
    476 
    477 				/* Send it to the main process */
    478 
    479 				ipc_send_command_to_main_process(module_index, in_buffer, (*packet_size + 3));
    480 			}
    481 		}
    482 
    483 		break;
    484 	}
    485 
    486 	return result;
    487 }
    488 
    489 /************************************************************************
    490  *                        ethernet_utils_write_socket     			    *
    491  ************************************************************************
    492 DESCRIPTION: write data to socket
    493 
    494 CONTEXT    : Only the same process that is writing to the socket
    495 ************************************************************************/
    496 int ethernet_utils_write_socket(int module_index, int length, unsigned char *buffer)
    497 {
    498 	int result;
    499 
    500 /*	console_printf_terminal("eth_utils, ethernet_utils_wipp_write() (length = %d).\n", length); */
    501 
    502 	/* Write to the socket */
    503 	result = write(SHARED_MEMORY_ETHERNET_SOCKET_ID(module_index), buffer, length);
    504 
    505 /*	console_printf_terminal("eth_utils, ethernet_utils_wipp_write() (result = %d).\n", result); */
    506 
    507 	if (result != length)
    508 	{
    509 		/**************************/
    510 		/* Error writing to port */
    511 		/************************/
    512 
    513 		console_printf_terminal("eth_utils, Error writing to %s socket (result = %d, errno = %d, error = %s)\n", ethernet_utils_module_names[module_index], result, errno, strerror(errno));
    514 
    515 		result = -1;
    516 	}
    517 
    518 	return result;
    519 }
    520 
    521 /************************************************************************
    522  *                        ethernet_utils_disconnect_socket 			    *
    523  ************************************************************************
    524 DESCRIPTION: Disconnect a socket
    525 
    526 CONTEXT    : Only the process that is disconnecting
    527 ************************************************************************/
    528 void ethernet_utils_disconnect_socket(int module_index)
    529 {
    530 	char temp_buf[6] = {'x','x','x', '5', '0', 0};
    531 
    532 	/* Switch to UART output */
    533 	SHARED_MEMORY_SWITCH_TO_UART_OUTPUT(module_index);
    534 
    535 	console_printf_terminal("eth_utils, disconnecting from %s socket.\n", ethernet_utils_module_names[module_index]);
    536 
    537 	switch (module_index)
    538 	{
    539 	case ETHERNET_UTILS_LOGGER_MODULE_ID:
    540 		/* Set debug path back to UART */
    541 		ipc_send_command_to_main_process(ETHERNET_UTILS_LOGGER_MODULE_ID, (unsigned char*)temp_buf, 5);
    542 		break;
    543 
    544 	case ETHERNET_UTILS_WIPP_MODULE_ID:
    545 		temp_buf[3] = WIPP_CONTROL_FROM_GENERAL_PROCESS_DEACTIVATE_IPERF;
    546 		ipc_send_command_to_main_process(GENERAL_PROCESS_MODULE_ID,(unsigned char*) temp_buf, 5);
    547 		break;
    548 	}
    549 
    550 	/* Close the socket */
    551 	close(SHARED_MEMORY_ETHERNET_SOCKET_ID(module_index));
    552 }
    553