Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4729 → Rev 4730

/branches/network/uspace/srv/net/tl/icmp/icmp.c
123,6 → 123,19
*/
typedef icmp_reply_timeout_t * icmp_reply_timeout_ref;
 
/** ICMP reply timeout data.
* Used as a timeouting fibril argument.
* @see icmp_timeout_for_reply()
*/
struct icmp_reply_timeout{
/** Reply data key.
*/
int reply_key;
/** Timeout in microseconds.
*/
suseconds_t timeout;
};
 
/** Processes the received ICMP packet.
* Is used as an entry point from the underlying IP module.
* Releases the packet on error.
252,19 → 265,6
*/
int icmp_bind_free_id( icmp_echo_ref echo_data );
 
/** ICMP reply timeout data.
* Used as a timeouting fibril argument.
* @see icmp_timeout_for_reply()
*/
struct icmp_reply_timeout{
/** Reply data key.
*/
int reply_key;
/** Timeout in microseconds.
*/
suseconds_t timeout;
};
 
/** ICMP global data.
*/
icmp_globals_t icmp_globals;
379,6 → 379,13
free( reply_timeout );
return icmp_release_and_return( packet, ENOMEM );
}
// prepare the timeouting thread
fibril = fibril_create( icmp_timeout_for_reply, reply_timeout );
if( ! fibril ){
free( reply );
free( reply_timeout );
return icmp_release_and_return( packet, EPARTY );
}
reply_timeout->reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
// timeout in microseconds
reply_timeout->timeout = timeout * 1000;
385,18 → 392,13
fibril_mutex_initialize( & reply->mutex );
fibril_mutex_lock( & reply->mutex );
fibril_condvar_initialize( & reply->condvar );
// start the timeouting fibril
fibril_add_ready( fibril );
index = icmp_replies_add( & icmp_globals.replies, reply_timeout->reply_key, reply );
if( index < 0 ){
free( reply );
free( reply_timeout );
return icmp_release_and_return( packet, index );
}
// start the timeouting thread
fibril = fibril_create( icmp_timeout_for_reply, reply_timeout );
if( ! fibril ){
return EPARTY;
}
fibril_add_ready( fibril );
 
// unlock the globals and wait for a reply
fibril_rwlock_write_unlock( & icmp_globals.lock );
406,6 → 408,7
 
// wait for a reply
fibril_condvar_wait( & reply->condvar, & reply->mutex );
 
// read the result
result = reply->result;
 
/branches/network/uspace/srv/net/tl/udp/udp.c
76,6 → 76,10
*/
#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING true
 
/** Default UDP autobind when sending via unbound sockets.
*/
#define NET_DEFAULT_UDP_AUTOBINDING true
 
/** Maximum UDP fragment size.
*/
#define MAX_UDP_FRAGMENT_SIZE 65535
90,13 → 94,22
 
/** Processes the received UDP packet queue.
* Is used as an entry point from the underlying IP module.
* Notifies the destination socket application.
* Releases the packet on error or send an ICMP error notification..
* Locks the global lock and calls udp_process_packet() function.
* @param device_id The device identifier. Ignored parameter.
* @param packet The received packet queue. Input/output parameter.
* @param receiver The target service. Ignored parameter.
* @param error The packet error reporting service. Prefixes the received packet. Input parameter.
* @returns EOK on success.
* @returns Other error codes as defined for the udp_process_packet() function.
*/
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
 
/** Processes the received UDP packet queue.
* Notifies the destination socket application.
* Releases the packet on error or sends an ICMP error notification..
* @param packet The received packet queue. Input/output parameter.
* @param error The packet error reporting service. Prefixes the received packet. Input parameter.
* @returns EOK on success.
* @returns EINVAL if the packet is not valid.
* @returns EINVAL if the stored packet address is not the an_addr_t.
* @returns EINVAL if the packet does not contain any data.
105,7 → 118,7
* @returns EADDRNOTAVAIL if the destination socket does not exist.
* @returns Other error codes as defined for the ip_client_process_packet() function.
*/
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
int udp_process_packet( packet_t packet, services_t error );
 
/** Releases the packet and returns the result.
* @param packet The packet queue to be released. Input parameter.
176,7 → 189,7
int udp_initialize( async_client_conn_t client_connection ){
ERROR_DECLARE;
 
measured_string_t names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }};
measured_string_t names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }, { "UDP_AUTOBINDING", 15 }};
measured_string_ref configuration;
size_t count = sizeof( names ) / sizeof( measured_string_t );
char * data;
198,6 → 211,7
udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
// get configuration
udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
configuration = & names[ 0 ];
ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data ));
if( configuration ){
204,6 → 218,9
if( configuration[ 0 ].value ){
udp_globals.checksum_computing = ( configuration[ 0 ].value[ 0 ] == 'y' );
}
if( configuration[ 1 ].value ){
udp_globals.autobinding = ( configuration[ 1 ].value[ 0 ] == 'y' );
}
net_free_settings( configuration, data );
}
fibril_rwlock_write_unlock( & udp_globals.lock );
211,6 → 228,16
}
 
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
int result;
 
fibril_rwlock_read_lock( & udp_globals.lock );
result = udp_process_packet( packet, error );
fibril_rwlock_read_unlock( & udp_globals.lock );
 
return result;
}
 
int udp_process_packet( packet_t packet, services_t error ){
ERROR_DECLARE;
 
size_t length;
276,8 → 303,10
tl_send_icmp_port_unreachable( udp_globals.net_phone, udp_globals.icmp_phone, packet, error );
return EADDRNOTAVAIL;
}
 
// trim after successful processing to be able to send an ICMP error message!
ERROR_PROPAGATE( packet_trim( packet, offset, 0 ));
 
// count the received packet fragments
next_packet = packet;
fragments = 0;
299,6 → 328,7
header->checksum = 0;
checksum = 0;
}
 
do{
++ fragments;
length = packet_get_data_length( next_packet );
329,6 → 359,7
checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
}
}while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
 
// check checksum
if( header->checksum ){
if( flip_checksum( compact_checksum( checksum ))){
338,6 → 369,7
return udp_release_and_return( packet, EINVAL );
}
}
 
// queue the received packet
if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
return udp_release_and_return( packet, ERROR_CODE );
356,11 → 388,9
* answer_count = 0;
switch( IPC_GET_METHOD( * call )){
case NET_TL_RECEIVED:
fibril_rwlock_read_lock( & udp_globals.lock );
if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
}
fibril_rwlock_read_unlock( & udp_globals.lock );
return ERROR_CODE;
case IPC_M_CONNECT_TO_ME:
return udp_process_client_messages( callid, * call );
491,18 → 521,22
socket = socket_cores_find( local_sockets, socket_id );
if( ! socket ) return ENOTSOCK;
 
// bind the socket to a random free port if not bound
while( socket->port <= 0 ){
// try to find a free port
fibril_rwlock_read_unlock( & udp_globals.lock );
fibril_rwlock_write_lock( & udp_globals.lock );
if( socket->port <= 0 ){
ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
// set the next port as the search starting port number
udp_globals.last_used_port = socket->port;
}
fibril_rwlock_write_unlock( & udp_globals.lock );
fibril_rwlock_read_lock( & udp_globals.lock );
if(( socket->port <= 0 ) && udp_globals.autobinding ){
// bind the socket to a random free port if not bound
do{
// try to find a free port
fibril_rwlock_read_unlock( & udp_globals.lock );
fibril_rwlock_write_lock( & udp_globals.lock );
// might be changed in the meantime
if( socket->port <= 0 ){
ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
// set the next port as the search starting port number
udp_globals.last_used_port = socket->port;
}
fibril_rwlock_write_unlock( & udp_globals.lock );
fibril_rwlock_read_lock( & udp_globals.lock );
// might be changed in the meantime
}while( socket->port <= 0 );
}
 
// TODO do not ask all the time
536,9 → 570,9
}
}
// set the udp header
header->source_port = htons( socket->port );
header->source_port = htons(( socket->port > 0 ) ? socket->port : 0 );
header->destination_port = htons( dest_port );
header->total_length = htons( total_length + sizeof( udp_header_t ));
header->total_length = htons( total_length + sizeof( * header ));
header->checksum = 0;
if( udp_globals.checksum_computing ){
if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
/branches/network/uspace/srv/net/tl/udp/udp.h
66,6 → 66,9
/** Indicates whether UDP checksum computing is enabled.
*/
int checksum_computing;
/** Indicates whether UDP autobnding on send is enabled.
*/
int autobinding;
/** Last used free port.
*/
int last_used_port;
/branches/network/uspace/srv/net/include/socket_errno.h
109,6 → 109,7
//#define HOST_NOT_FOUND (-11001)
//#define TRY_AGAIN (-11002)
//#define NO_RECOVERY (-11003)
 
/** No data.
*/
#define NO_DATA (-11004)
/branches/network/uspace/srv/net/net/net.c
351,6 → 351,7
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ERROR_REPORTING", "yes" )); //anything else not starting with 'y'
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ECHO_REPLYING", "yes" )); //anything else not starting with 'y'
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "UDP_CHECKSUM_COMPUTING", "yes" )); //anything else not starting with 'y'
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "UDP_AUTOBINDING", "yes" )); //anything else not starting with 'y'
return EOK;
}
 
/branches/network/uspace/srv/net/net/Makefile
61,6 → 61,7
$(NET_BASE)tl/icmp/icmp.c \
$(NET_BASE)tl/icmp/icmp_client.c \
$(NET_BASE)tl/tcp/tcp.c \
$(NET_BASE)tl/tl_common.c \
$(NET_BASE)tl/udp/udp.c \
$(STRUCTURES)dynamic_fifo.c
 
/branches/network/uspace/srv/net/socket/socket_core.c
80,7 → 80,7
// already used
return EADDRINUSE;
}
// disbind if bound
// unbind if bound
socket_ports_exclude( global_sockets, socket->port );
socket->port = -1;
return socket_bind_insert( global_sockets, socket, address_in->sin_port );