Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4712 → Rev 4713

/branches/network/uspace/srv/net/tl/udp/udp.c
56,7 → 56,7
#include "../../include/ip_protocols.h"
#include "../../include/icmp_client.h"
#include "../../include/icmp_interface.h"
#include "../../include/socket.h"
#include "../../include/socket_codes.h"
#include "../../include/socket_errno.h"
 
#include "../../socket/socket_core.h"
104,7 → 104,7
* @param result The result to be returned. Input parameter.
* @return The result parameter.
*/
static int release_and_return( packet_t packet, int result );
int udp_release_and_return( packet_t packet, int result );
 
/** Sends the port unreachable ICMP notification.
* Sends the first packet and releases all the others.
125,7 → 125,7
* @returns EOK on success.
* @see socket.h
*/
int process_client_messages( ipc_callid_t callid, ipc_call_t call );
int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
 
/** Sends data from the socket to the remote address.
* Binds the socket to a free port if not already connected/bound.
248,35 → 248,35
// length = icmp_client_header_length( packet );
result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
if( result < 0 ){
return release_and_return( packet, result );
return udp_release_and_return( packet, result );
}
printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
length = ( size_t ) result;
if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
return release_and_return( packet, ERROR_CODE );
return udp_release_and_return( packet, ERROR_CODE );
}
break;
default:
return release_and_return( packet, ENOTSUP );
return udp_release_and_return( packet, ENOTSUP );
}
}
// TODO process received ipopts?
result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
if( result < 0 ){
return release_and_return( packet, result );
return udp_release_and_return( packet, result );
}
offset = ( size_t ) result;
 
length = packet_get_data_length( packet );
if( length <= 0 ){
return release_and_return( packet, EINVAL );
return udp_release_and_return( packet, EINVAL );
}
if( length < sizeof( udp_header_t ) + offset ){
return release_and_return( packet, NO_DATA );
return udp_release_and_return( packet, NO_DATA );
}
data = packet_get_data( packet );
if( ! data ){
return release_and_return( packet, NO_DATA );
return udp_release_and_return( packet, NO_DATA );
}
// get udp header
header = ( udp_header_ref )( data + offset );
296,12 → 296,12
++ fragments;
length = packet_get_data_length( packet );
if( length <= 0 ){
return release_and_return( packet, NO_DATA );
return udp_release_and_return( packet, NO_DATA );
}
if( total_length < length ){
// cut of the suffix if too long
if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
return release_and_return( packet, ERROR_CODE );
return udp_release_and_return( packet, ERROR_CODE );
}
// relese the rest of the packet fragments
tmp_packet = pq_next( next_packet );
319,7 → 319,7
}while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
// queue the received packet
if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
return release_and_return( packet, ERROR_CODE );
return udp_release_and_return( packet, ERROR_CODE );
}
 
// notify the destination socket
342,14 → 342,12
fibril_rwlock_read_unlock( & udp_globals.lock );
return ERROR_CODE;
case IPC_M_CONNECT_TO_ME:
return process_client_messages( callid, * call );
return udp_process_client_messages( callid, * call );
}
return ENOTSUP;
}
 
int process_client_messages( ipc_callid_t callid, ipc_call_t call ){
ERROR_DECLARE;
 
int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
int res;
bool keep_on_going = true;
socket_cores_t local_sockets;
371,15 → 369,7
 
while( keep_on_going ){
// refresh data
answer_count = 0;
IPC_SET_RETVAL( answer, 0 );
// just to be precize
IPC_SET_METHOD( answer, 0 );
IPC_SET_ARG1( answer, 0 );
IPC_SET_ARG2( answer, 0 );
IPC_SET_ARG3( answer, 0 );
IPC_SET_ARG4( answer, 0 );
IPC_SET_ARG5( answer, 0 );
refresh_answer( & answer, & answer_count );
 
callid = async_get_call( & call );
// printf( "message %d\n", IPC_GET_METHOD( * call ));
398,28 → 388,26
answer_count = 3;
break;
case NET_SOCKET_BIND:
if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
res = ERROR_CODE;
break;
res = socket_read_data( & addr, & addrlen );
if( res == EOK ){
fibril_rwlock_write_lock( & lock );
fibril_rwlock_write_lock( & udp_globals.lock );
res = socket_bind( & local_sockets, & udp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port );
fibril_rwlock_write_unlock( & udp_globals.lock );
fibril_rwlock_write_unlock( & lock );
free( addr );
}
fibril_rwlock_write_lock( & lock );
fibril_rwlock_write_lock( & udp_globals.lock );
res = socket_bind( & local_sockets, & udp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port );
fibril_rwlock_write_unlock( & udp_globals.lock );
fibril_rwlock_write_unlock( & lock );
free( addr );
break;
break;
case NET_SOCKET_SENDTO:
if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
res = ERROR_CODE;
break;
res = socket_read_data( & addr, & addrlen );
if( res == EOK ){
fibril_rwlock_read_lock( & lock );
fibril_rwlock_read_lock( & udp_globals.lock );
res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call ));
fibril_rwlock_read_unlock( & udp_globals.lock );
fibril_rwlock_read_unlock( & lock );
free( addr );
}
fibril_rwlock_read_lock( & lock );
fibril_rwlock_read_lock( & udp_globals.lock );
res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call ));
fibril_rwlock_read_unlock( & udp_globals.lock );
fibril_rwlock_read_unlock( & lock );
free( addr );
break;
case NET_SOCKET_RECVFROM:
fibril_rwlock_read_lock( & lock );
450,20 → 438,7
 
// printf( "res = %d\n", res );
 
switch( answer_count ){
case 0: ipc_answer_0( callid, ( ipcarg_t ) res );
continue;
case 1: ipc_answer_1( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ));
continue;
case 2: ipc_answer_2( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ));
continue;
case 3: ipc_answer_3( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ), IPC_GET_ARG3( answer ));
continue;
case 4: ipc_answer_4( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ), IPC_GET_ARG3( answer ), IPC_GET_ARG4( answer ));
continue;
default: ipc_answer_5( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ), IPC_GET_ARG3( answer ), IPC_GET_ARG4( answer ), IPC_GET_ARG5( answer ));
continue;
}
answer_call( callid, res, & answer, answer_count );
}
 
socket_cores_destroy( & local_sockets );
494,15 → 469,17
if( ! socket ) return ENOTSOCK;
 
// bind the socket to a random free port if not bound
if( socket->port <= 0 ){
while( socket->port <= 0 ){
// try to find a free port
fibril_rwlock_read_unlock( & udp_globals.lock );
fibril_rwlock_write_lock( & udp_globals.lock );
ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
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 );
// set the next port as the search starting port number
udp_globals.last_used_port = socket->port;
}
// TODO do not ask all the time
ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
521,7 → 498,7
for( index = 1; index < fragments; ++ index ){
result = socket_read_packet_data( & next_packet, 0, address_in );
if( result < 0 ){
return release_and_return( packet, result );
return udp_release_and_return( packet, result );
}
packet = pq_add( packet, next_packet, index, 0 );
total_length += ( size_t ) result;
687,7 → 664,7
return ( int ) length;
}
 
static int release_and_return( packet_t packet, int result ){
int udp_release_and_return( packet_t packet, int result ){
pq_release( udp_globals.net_phone, packet_get_id( packet ));
return result;
}
710,7 → 687,7
&& ( packet_set_addr( packet, src, src, ( size_t ) length ) == EOK )){
icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
}else{
release_and_return( packet, EINVAL );
udp_release_and_return( packet, EINVAL );
}
}