eth_utils.c revision 64064216a8433360745f69edddce19a606659163
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
40extern 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
63unsigned char ethernet_utils_welcome_message[] = {'W', 2, 0, 2, ETH_UTILS_PROTOCOL_VERSION};
64
65char 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
77int ethernet_utils_init_module(int module_index, u_short port_number, int *module_pipe, unsigned char mux_uart_id);
78void ethernet_utils_signal_handler(int signal);
79int 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);
80int ethernet_utils_write_socket(int module_index, int length, unsigned char *buffer);
81void ethernet_utils_disconnect_socket(int module_index);
82
83	/**************/
84	/* Functions */
85	/************/
86
87/************************************************************************
88 *                        ethernet_utils_init                           *
89 ************************************************************************
90DESCRIPTION: Initialize the ethernet communication
91
92CONTEXT	   : main process only!
93************************************************************************/
94void 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 ************************************************************************
104DESCRIPTION: Deinitialize the ethernet communication
105
106CONTEXT	   : main process only!
107************************************************************************/
108void 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 ************************************************************************
132DESCRIPTION: Signal handler - receive the USER
133
134CONTEXT	   : Signal owner
135************************************************************************/
136void ethernet_utils_signal_handler(int signal)
137{
138}
139
140/************************************************************************
141 *                        ethernet_utils_init_module                    *
142 ************************************************************************
143DESCRIPTION: Initialize ethernet communication
144
145RETURNS:   : Process ID of the new process or -1 if error.
146
147CONTEXT	   : main process only!
148************************************************************************/
149int 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 ************************************************************************
393DESCRIPTION: Handle In commands
394
395CONTEXT	   : Only the same process that is reading from the socket
396************************************************************************/
397int 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 ************************************************************************
492DESCRIPTION: write data to socket
493
494CONTEXT    : Only the same process that is writing to the socket
495************************************************************************/
496int 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 ************************************************************************
524DESCRIPTION: Disconnect a socket
525
526CONTEXT    : Only the process that is disconnecting
527************************************************************************/
528void 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