void __po_hi_c_driver_eth_leon_poller (const __po_hi_device_id dev_id) { (void) dev_id; __DEBUGMSG ("Poller launched, device-id=%d\n", leon_eth_device_id); socklen_t socklen = sizeof (struct sockaddr); /* See ACCEPT (2) for details on initial value of socklen */ __po_hi_uint32_t len; int sock; int max_socket; fd_set selector; struct sockaddr_in sa; __po_hi_device_id dev; __po_hi_node_t dev_init; int established = 0; __po_hi_protocol_conf_t* protocol_conf; unsigned long* swap_pointer; unsigned long swap_value; max_socket = 0; /* Used to compute the max socket number, useful for listen() call */ /* * We initialize each node socket with -1 value. This value means * that the socket is not active. */ for (dev = 0 ; dev < __PO_HI_NB_DEVICES ; dev++) { rnodes[dev].socket = -1; } /* * Create a socket for each node that will communicate with us. */ for (dev = 0; dev < __PO_HI_NB_DEVICES ; dev++) { if (dev != leon_eth_device_id) { __PO_HI_SET_SOCKET_TIMEOUT(nodes[leon_eth_device_id].socket,500000); established = 0; while (established == 0) { __DEBUGMSG ("[DRIVER ETH] Poller waits for connection with device %d on socket %d (waiting device %d)\n", dev, nodes[leon_eth_device_id].socket, leon_eth_device_id); sock = accept (nodes[leon_eth_device_id].socket, (struct sockaddr*) &sa, &socklen); if (sock == -1) { __DEBUGMSG ("[DRIVER ETH] accept() error for device %d on device %d (socket=%d)\n", dev, leon_eth_device_id, nodes[leon_eth_device_id].socket); continue; } __PO_HI_SET_SOCKET_TIMEOUT(sock,100000); #ifndef __PO_HI_USE_PROTOCOL_MYPROTOCOL_I if (read (sock, &dev_init, sizeof (__po_hi_device_id)) != sizeof (__po_hi_device_id)) { established = 0; __DEBUGMSG ("[DRIVER ETH] Cannot read device-id for device %d, socket=%d\n", dev, sock); } else { __DEBUGMSG ("[DRIVER ETH] read device-id %d from socket=%d\n", dev_init, sock); established = 1; } #else established = 1; #endif } rnodes[dev].socket = sock; if (sock > max_socket ) { max_socket = sock; } } } __DEBUGMSG ("[DRIVER ETH] Poller initialization finished, waiting for other tasks\n"); __po_hi_wait_initialization (); __DEBUGMSG ("[DRIVER ETH] Other tasks are initialized, let's start the polling !\n"); /* * Then, listen and receive data on the socket, identify the node * which send the data and put it in its message queue */ while (1) { FD_ZERO( &selector ); for (dev = 0; dev < __PO_HI_NB_DEVICES ; dev++) { if ( (dev != leon_eth_device_id ) && ( rnodes[dev].socket != -1 ) ) { FD_SET( rnodes[dev].socket , &selector ); } } if (select (max_socket + 1, &selector, NULL, NULL, NULL) == -1 ) { #ifdef __PO_HI_DEBUG __DEBUGMSG ("[DRIVER ETH] Error on select for node %d\n", __po_hi_mynode); #endif } #ifdef __PO_HI_DEBUG __DEBUGMSG ("[DRIVER ETH] Receive message\n"); #endif for (dev = 0; dev < __PO_HI_NB_DEVICES ; dev++) { __DEBUGMSG ("[DRIVER ETH] Try to watch if it comes from device %d (socket=%d)\n", dev, rnodes[dev].socket); if ( (rnodes[dev].socket != -1 ) && FD_ISSET(rnodes[dev].socket, &selector)) { __DEBUGMSG ("[DRIVER ETH] Receive message from dev %d\n", dev); #ifdef __PO_HI_USE_PROTOCOL_MYPROTOCOL_I { protocol_conf = __po_hi_transport_get_protocol_configuration (virtual_bus_myprotocol_i); int datareceived; len = recv (rnodes[dev].socket, &datareceived, sizeof (int), MSG_WAITALL); __DEBUGMSG ("[DRIVER ETH] Message received len=%d\n",(int)len); if (len == 0) { __DEBUGMSG ("[DRIVER ETH] Zero size from device %d\n",dev); rnodes[dev].socket = -1; continue; } protocol_conf->unmarshaller (& __po_hi_c_driver_eth_leon_poller_received_request, &datareceived, len); __po_hi_c_driver_eth_leon_poller_received_request.port = 1; } #else memset (__po_hi_c_driver_eth_leon_poller_msg.content, '\0', __PO_HI_MESSAGES_MAX_SIZE); len = recv (rnodes[dev].socket, __po_hi_c_driver_eth_leon_poller_msg.content, __PO_HI_MESSAGES_MAX_SIZE, MSG_WAITALL); __po_hi_c_driver_eth_leon_poller_msg.length = len; __DEBUGMSG ("[DRIVER ETH] Message received len=%d\n",(int)len); #ifdef __PO_HI_DEBUG __po_hi_messages_debug (&msg); #endif if (len == 0) { __DEBUGMSG ("[DRIVER ETH] Zero size from device %d\n",dev); rnodes[dev].socket = -1; continue; } swap_pointer = (unsigned long*) &__po_hi_c_driver_eth_leon_poller_msg.content[0]; swap_value = *swap_pointer; *swap_pointer = __po_hi_swap_byte (swap_value); __po_hi_unmarshall_request (& __po_hi_c_driver_eth_leon_poller_received_request, &__po_hi_c_driver_eth_leon_poller_msg); #endif __po_hi_main_deliver (& __po_hi_c_driver_eth_leon_poller_received_request); } } } }
void __po_hi_c_driver_eth_leon_init (__po_hi_device_id id) { int i; int ret; int reuse; char *tmp; __po_hi_uint16_t dev; __po_hi_time_t mytime; __po_hi_time_t tmptime; __po_hi_time_t current_time; struct sockaddr_in sa; struct hostent* hostinfo; __po_hi_c_ip_conf_t* ipconf; char ip_addr[16]; unsigned short ip_port; int node; ipconf = (__po_hi_c_ip_conf_t*)__po_hi_get_device_configuration (id); netdriver_config.ip_address = ipconf->address; if (ipconf->exist.netmask == 1) { netdriver_config.ip_netmask = ipconf->netmask; } if (ipconf->exist.gateway == 1) { rtems_bsdnet_config.gateway = ipconf->gateway; } if (ipconf->exist.dns == 1) { rtems_bsdnet_config.name_server[0] = ipconf->dns; } rtems_bsdnet_initialize_network (); /* #ifdef __PO_HI_DEBUG_INFO rtems_bsdnet_show_if_stats (); rtems_bsdnet_show_inet_routes (); rtems_bsdnet_show_ip_stats (); #endif */ leon_eth_device_id = id; __po_hi_transport_set_sending_func (leon_eth_device_id, __po_hi_c_driver_eth_leon_sender); for (node = 0 ; node < __PO_HI_NB_DEVICES ; node++) { nodes[node].socket = -1; } ip_port = (unsigned short)ipconf->port; __DEBUGMSG ("My configuration, addr=%s, port=%d\n", ipconf->address, ip_port); /* * If the current node port has a port number, then it has to * listen to other nodes. So, we create a socket, bind it and * listen to other nodes. */ if (ip_port != 0) { nodes[id].socket = socket (AF_INET, SOCK_STREAM, 0); if (nodes[id].socket == -1 ) { #ifdef __PO_HI_DEBUG __DEBUGMSG ("Cannot create socket for device %d\n", id); #endif return; } __DEBUGMSG ("[DRIVER ETH] Receiving socket for device %d created, value=%d\n", id, nodes[id].socket); sa.sin_addr.s_addr = htonl (INADDR_ANY); /* We listen on all adresses */ sa.sin_family = AF_INET; sa.sin_port = htons (ip_port); /* Port provided by the generated code */ if( bind (nodes[id].socket , (struct sockaddr *) &sa , sizeof (struct sockaddr_in) ) == -1 ) { __DEBUGMSG ("Unable to bind socket and port on socket %d\n", nodes[id].socket); } if( listen( nodes[id].socket , __PO_HI_NB_ENTITIES ) == -1) { __DEBUGMSG ("Cannot listen on socket %d\n", nodes[id].socket); } __DEBUGMSG ("[DRIVER ETH] Receiving socket listen on any address on port %d\n", sa.sin_port); /* * Create the thread which receive all data from other * nodes. This thread will execute the function * __po_hi_receiver_task */ __po_hi_initialize_add_task (); __po_hi_create_generic_task (-1, 0,__PO_HI_MAX_PRIORITY, 0, (void* (*)(void)) __po_hi_c_driver_eth_leon_poller, NULL); } /* * For each node in the sytem that may communicate with the current * node we create a socket. This socket will be used to send data. */ for (dev = 0 ; dev < __PO_HI_NB_DEVICES ; dev++ ) { if (dev == id) { continue; } __DEBUGMSG ("[DRIVER ETH] Will initialize connection with device %d\n", dev); memset (ip_addr, '\0', 16); ip_port = 0; ipconf = (__po_hi_c_ip_conf_t*) __po_hi_get_device_configuration (dev); ip_port = (unsigned short)ipconf->port; __DEBUGMSG ("[DRIVER ETH] Configuration for device %d, addr=%s, port=%d\n", dev, ipconf->address, ip_port); if (ip_port == 0) { __DEBUGMSG ("[DRIVER ETH] Invalid remote port\n"); continue; } while (1) { nodes[dev].socket = socket (AF_INET, SOCK_STREAM, 0); if (nodes[dev].socket == -1 ) { __DEBUGMSG ("[DRIVER ETH] Socket for dev %d is not created\n", dev); return; } __DEBUGMSG ("[DRIVER ETH] Socket for dev %d created, value=%d\n", dev, nodes[dev].socket); hostinfo = gethostbyname ((char*)ipconf->address); if (hostinfo == NULL ) { __DEBUGMSG ("[DRIVER ETH] Error while getting host informations for device %d\n", dev); } __DEBUGMSG ("[DRIVER ETH] Got the following information for device %d\n", dev); sa.sin_port = htons (ip_port); sa.sin_family = AF_INET; /* The following lines are used to copy the * hostinfo->h_length to the sa.sin_addr member. Most * of program use the memcpy to do that, but the * RT-POSIX profile we use forbid the use of this * function. We use a loop instead to perform the * copy. So, these lines replace the code : * * * memcpy( (char*) &( sa.sin_addr ) , (char*)hostinfo->h_addr , hostinfo->h_length ); */ tmp = (char*) &(sa.sin_addr); for (i=0 ; i<hostinfo->h_length ; i++) { tmp[i] = hostinfo->h_addr[i]; } __PO_HI_SET_SOCKET_TIMEOUT(nodes[dev].socket,100000); /* * We try to connect on the remote host. We try every * second to connect on. */ ret = connect (nodes[dev].socket, (struct sockaddr*) &sa , sizeof (struct sockaddr_in)); #ifdef __PO_HI_USE_PROTOCOL_MYPROTOCOL_I if (ret == 0) { __DEBUGMSG ("[DRIVER ETH] Connection established with device %d, socket=%d\n", dev, nodes[dev].socket); break; } else { __DEBUGMSG ("connect() failed, return=%d\n", ret); } #else if (ret == 0) { __DEBUGMSG ("[DRIVER ETH] Send my id (%d) using socket %d (node %d)\n", id, nodes[dev].socket, dev); ret = write (nodes[dev].socket, &id, sizeof (__po_hi_device_id)); if (ret != sizeof (__po_hi_device_id)) { __DEBUGMSG ("[DRIVER ETH] Device %d cannot send his id (ret=%d)\n", id, ret); } __DEBUGMSG ("[DRIVER ETH] Connection established with device %d, socket=%d (ret=%d)\n", dev, nodes[dev].socket, ret); break; } else { __DEBUGMSG ("connect() failed, return=%d\n", ret); } #endif if (close (nodes[dev].socket)) { __DEBUGMSG ("[DRIVER ETH] Cannot close socket %d\n", nodes[dev].socket); } /* * We wait 500ms each time we try to connect on the * remote host */ __po_hi_get_time (¤t_time); __po_hi_milliseconds (&tmptime, 500); __po_hi_add_times (&mytime, ¤t_time, &tmptime); __DEBUGMSG ("[DRIVER ETH] Cannot connect on device %d, wait 500ms\n", dev); __po_hi_delay_until (&mytime); } } __DEBUGMSG ("[DRIVER ETH] INITIALIZATION DONE\n"); }
void __po_hi_driver_sockets_init (__po_hi_device_id dev_id) { int ret; #ifdef _WIN32 char FAR reuse; #else int reuse; #endif struct sockaddr_in sa; unsigned short ip_port; __po_hi_c_ip_conf_t* ipconf; __po_hi_device_id dev; __po_hi_device_id sent_id; struct hostent* hostinfo; __po_hi_time_t mytime; __po_hi_time_t tmptime; char *tmp; __po_hi_time_t current_time; int i; __po_hi_c_sockets_listen_socket = -1; __po_hi_c_sockets_device_id = dev_id; if (__po_hi_c_sockets_array_init_done == 0) { for (dev = 0 ; dev < __PO_HI_NB_DEVICES ; dev++) { __po_hi_c_sockets_read_sockets[dev] = -1; __po_hi_c_sockets_write_sockets[dev] = -1; } __po_hi_c_sockets_array_init_done = 1; } __po_hi_transport_set_sending_func (dev_id, __po_hi_driver_sockets_send); ipconf = (__po_hi_c_ip_conf_t*)__po_hi_get_device_configuration (dev_id); ip_port = ipconf->port; __DEBUGMSG ("My configuration, addr=%s, port=%d\n", ipconf->address, ip_port ); /* * If the current node port has a port number, then it has to * listen to other nodes. So, we create a socket, bind it and * listen to other nodes. */ if (ip_port != 0) { __po_hi_c_sockets_listen_socket = socket (AF_INET, SOCK_STREAM, 0); if (__po_hi_c_sockets_listen_socket == -1 ) { #ifdef __PO_HI_DEBUG __DEBUGMSG ("Cannot create socket for device %d\n", dev_id); #endif return; } __DEBUGMSG ("Socket created for addr=%s, port=%d, socket value=%d\n", ipconf->address, ip_port, __po_hi_c_sockets_listen_socket); reuse = 1; if (setsockopt (__po_hi_c_sockets_listen_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse))) { __DEBUGMSG ("[DRIVER SOCKETS] Error while making the receiving socket reusable\n"); } sa.sin_addr.s_addr = htonl (INADDR_ANY); /* We listen on all adresses */ sa.sin_family = AF_INET; sa.sin_port = htons (ip_port); /* Port provided by the generated code */ if( bind (__po_hi_c_sockets_listen_socket, (struct sockaddr *) &sa , sizeof (struct sockaddr_in) ) < 0 ) { __DEBUGMSG ("Unable to bind socket and port on socket %d\n", __po_hi_c_sockets_listen_socket); } if( listen (__po_hi_c_sockets_listen_socket, __PO_HI_NB_DEVICES) < 0 ) { __DEBUGMSG ("Cannot listen on socket %d\n", __po_hi_c_sockets_listen_socket); } /* * Create the thread which receive all data from other * nodes. This thread will execute the function * __po_hi_receiver_task */ __po_hi_initialize_add_task (); __po_hi_create_generic_task (-1, 0,__PO_HI_MAX_PRIORITY, 0, 0, (void* (*)(void))__po_hi_sockets_poller, &dev_id); /* For now, we force affinity to 0 */ } /* * For each node in the sytem that may communicate with the current * node we create a socket. This socket will be used to send data. */ for (dev = 0 ; dev < __PO_HI_NB_DEVICES ; dev++) { if (dev == dev_id) { continue; } if (__po_hi_transport_share_bus (dev, dev_id) == 0) { __DEBUGMSG ("[DRIVER SOCKETS] Device %d and device %d does not share the same bus, skip connecting them\n", dev, dev_id); continue; } __DEBUGMSG ("[DRIVER SOCKETS] Will initialize connection with device %d\n", dev); ip_port = 0; ipconf = (__po_hi_c_ip_conf_t*) __po_hi_get_device_configuration (dev); ip_port = (unsigned short)ipconf->port; __DEBUGMSG ("[DRIVER SOCKETS] Configuration for device %d, port=%d\n", dev, ip_port); if (ip_port == 0) { __DEBUGMSG ("[DRIVER SOCKETS] Invalid remote port\n"); continue; } while (1) { __po_hi_c_sockets_write_sockets[dev] = socket (AF_INET, SOCK_STREAM, 0); if (__po_hi_c_sockets_write_sockets[dev] == -1 ) { __DEBUGMSG ("[DRIVER SOCKETS] Socket for dev %d is not created\n", dev); return; } int NoDelayFlag = 1; if(setsockopt(__po_hi_c_sockets_write_sockets[dev],IPPROTO_TCP,TCP_NODELAY,&NoDelayFlag,sizeof(NoDelayFlag))){ __DEBUGMSG ("[DRIVER SOCKETS] Unable to set TCP_NODELAY for dev %d\n", dev); } __DEBUGMSG ("[DRIVER SOCKETS] Socket for dev %d created, value=%d\n", dev, __po_hi_c_sockets_write_sockets[dev]); hostinfo = NULL; hostinfo = gethostbyname ((char*)ipconf->address); if (hostinfo == NULL ) { __DEBUGMSG ("[DRIVER SOCKETS] Error while getting host informations for device %d\n", dev); } sa.sin_port = htons (ip_port); sa.sin_family = AF_INET; /* The following lines are used to copy the * hostinfo->h_length to the sa.sin_addr member. Most * of program use the memcpy to do that, but the * RT-POSIX profile we use forbid the use of this * function. We use a loop instead to perform the * copy. So, these lines replace the code : * * * memcpy( (char*) &( sa.sin_addr ) , (char*)hostinfo->h_addr , hostinfo->h_length ); */ tmp = (char*) &(sa.sin_addr); for (i=0 ; i<hostinfo->h_length ; i++) { tmp[i] = hostinfo->h_addr[i]; } /* * We try to connect on the remote host. We try every * second to connect on. */ __PO_HI_SET_SOCKET_TIMEOUT(__po_hi_c_sockets_write_sockets[dev], 500000); ret = connect (__po_hi_c_sockets_write_sockets[dev], (struct sockaddr*) &sa , sizeof (struct sockaddr_in)); #ifdef __PO_HI_USE_PROTOCOL_MYPROTOCOL_I if (ret == 0) { __DEBUGMSG ("[DRIVER SOCKETS] Connection established with device %d, socket=%d\n", dev, __po_hi_c_sockets_write_sockets[dev]); break; } else { __DEBUGMSG ("connect() failed, return=%d\n", ret); } #else if (ret == 0) { __DEBUGMSG ("[DRIVER SOCKETS] Send my id (%d) to device %d through socket %d\n", dev_id, dev , __po_hi_c_sockets_write_sockets[dev]); sent_id = __po_hi_swap_byte (dev_id); #ifdef _WIN32 ret = send (__po_hi_c_sockets_write_sockets[dev], (char*) &sent_id, sizeof (__po_hi_device_id), 0); #else ret = write (__po_hi_c_sockets_write_sockets[dev], &sent_id, sizeof (__po_hi_device_id)); #endif if (ret != sizeof (__po_hi_device_id)) { __DEBUGMSG ("[DRIVER SOCKETS] Device %d cannot send his id, expected size=%d, return value=%d\n", dev_id, sizeof (__po_hi_device_id), ret); } else { __DEBUGMSG ("[DRIVER SOCKETS] Connection established with device %d, socket=%d\n", dev, __po_hi_c_sockets_write_sockets[dev]); break; } } else { __DEBUGMSG ("connect() failed, return=%d\n", ret); } #endif if (close (__po_hi_c_sockets_write_sockets[dev])) { __DEBUGMSG ("[DRIVER SOCKETS] Cannot close socket %d\n", __po_hi_c_sockets_write_sockets[dev]); } /* * We wait 500ms each time we try to connect on the * remote host */ __po_hi_get_time (¤t_time); __po_hi_milliseconds (&tmptime, 500); __po_hi_add_times (&mytime, ¤t_time, &tmptime); __DEBUGMSG ("[DRIVER SOCKETS] Cannot connect on device %d, wait 500ms\n", dev); __po_hi_delay_until (&mytime); } } __DEBUGMSG ("[DRIVER SOCKETS] INITIALIZATION DONE\n"); }