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