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