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 ************************************************************************/
ethernet_utils_init()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 ************************************************************************/
ethernet_utils_deinit()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 ************************************************************************/
ethernet_utils_signal_handler(int signal)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 ************************************************************************/
ethernet_utils_init_module(int module_index,u_short port_number,int * module_pipe,unsigned char mux_uart_id)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 ************************************************************************/
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)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 ************************************************************************/
ethernet_utils_write_socket(int module_index,int length,unsigned char * buffer)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 ************************************************************************/
ethernet_utils_disconnect_socket(int module_index)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