Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4706 → Rev 4707

/branches/network/uspace/srv/net/tl/tcp/tcp.c
54,35 → 54,42
#include "tcp.h"
#include "tcp_module.h"
 
/** Free ports pool start.
*/
#define TCP_FREE_PORTS_START 1025
 
/** Free ports pool end.
*/
#define TCP_FREE_PORTS_END 65535
 
/** TCP global data.
*/
tcp_globals_t tcp_globals;
 
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver );
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
 
/** Initializes the module.
*/
int tcp_initialize( async_client_conn_t client_connection ){
// ERROR_DECLARE;
ERROR_DECLARE;
 
// ipcarg_t arg1, arg2;
// packet_t packet;
 
/* printf( "TCP - testing to send to IP:\n" );
ERROR_PROPAGATE( ip_echo( tcp_globals.ip_phone, 12, 34, 0, 0, 0, & arg1, & arg2, NULL, NULL, NULL ));
if(( arg1 != 12 ) || ( arg2 != 34 )) return EINVAL;
printf( "OK\n" );
*/
fibril_rwlock_initialize( & tcp_globals.lock );
fibril_rwlock_write_lock( & tcp_globals.lock );
tcp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP );
if( tcp_globals.icmp_phone < 0 ){
return tcp_globals.icmp_phone;
}
tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg );
/* printf( "TCP - testing to send packet to IP:\n" );
packet = packet_get_4( tcp_globals.net_phone, 6, 20, 30, 20 );
if( ! packet ) return ENOMEM;
packet_copy_data( packet, "Hi, this is TCP", 16 );
ip_send_msg( tcp_globals.ip_phone, -1, packet, SERVICE_TCP );
printf( "OK\n" );
*/ return EOK;
if( tcp_globals.ip_phone < 0 ){
return tcp_globals.ip_phone;
}
ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets ));
tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
fibril_rwlock_write_unlock( & tcp_globals.lock );
return EOK;
}
 
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver ){
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
// TODO received
// TODO remove debug dump:
uint8_t * data;
104,7 → 111,7
return EOK;
case NET_TL_RECEIVED:
ERROR_PROPAGATE( packet_translate( tcp_globals.net_phone, & packet, IPC_GET_PACKET( call )));
return tcp_received_msg( IPC_GET_DEVICE( call ), packet, 0 );
return tcp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_TCP, IPC_GET_ERROR( call ));
}
return ENOTSUP;
}
/branches/network/uspace/srv/net/tl/tcp/tcp.h
31,17 → 31,42
*/
 
/** @file
* \todo
* TCP module.
*/
 
#ifndef __NET_TCP_H__
#define __NET_TCP_H__
 
#include <fibril_sync.h>
 
#include "../../socket/socket_core.h"
 
/** Type definition of the TCP global data.
* @see tcp_globals
*/
typedef struct tcp_globals tcp_globals_t;
 
/** TCP global data.
*/
struct tcp_globals{
int ip_phone;
int net_phone;
/** Networking module phone.
*/
int net_phone;
/** IP module phone.
*/
int ip_phone;
/** ICMP module phone.
*/
int icmp_phone;
/** Last used free port.
*/
int last_used_port;
/** Active sockets.
*/
socket_ports_t sockets;
/** Safety lock.
*/
fibril_rwlock_t lock;
};
 
#endif
/branches/network/uspace/srv/net/tl/tcp/Makefile
44,7 → 44,10
$(STRUCTURES)packet/packet_client.c \
$(STRUCTURES)packet/packet_remote.c \
$(STRUCTURES)measured_strings.c \
$(NET_BASE)il/ip/ip_client.c \
$(NET_BASE)il/ip/ip_remote.c \
$(NET_BASE)il/icmp/icmp_remote.c \
$(NET_BASE)il/icmp/icmp_client.c \
$(NET_BASE)net/net_remote.c
 
include $(NET_BASE)Makefile.module
/branches/network/uspace/srv/net/tl/udp/udp.c
38,7 → 38,6
#include <async.h>
#include <fibril_sync.h>
#include <malloc.h>
#include <stdio.h>
 
#include <ipc/ipc.h>
#include <ipc/services.h>
55,6 → 54,8
#include "../../include/ip_client.h"
#include "../../include/ip_interface.h"
#include "../../include/ip_protocols.h"
#include "../../include/icmp_client.h"
#include "../../include/icmp_interface.h"
#include "../../include/socket.h"
#include "../../include/socket_errno.h"
 
79,21 → 80,15
*/
#define UDP_FREE_PORTS_END 65535
 
/** Processes the received UDP packet.
/** Processes the received UDP packet queue.
* Is used as an entry point from the underlying IP module.
* Releases the packet on error.
* Notifies the destination socket application.
* Releases the packet on error or send an ICMP error notification..
* @param device_id The device identifier. Ignored parameter.
* @param packet The received packet. Input/output 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 );
 
/** Processes the received UDP packet.
* Notifies the destination socket application.
* @param packet The received packet. Input/output 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.
102,8 → 97,23
* @returns EADDRNOTAVAIL if the destination socket does not exist.
* @returns Other error codes as defined for the ip_client_process_packet() function.
*/
int udp_process_packet( packet_t packet );
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
 
/** Releases the packet and returns the result.
* @param packet The packet queue to be released. Input parameter.
* @param result The result to be returned. Input parameter.
* @return The result parameter.
*/
static int release_and_return( packet_t packet, int result );
 
/** Sends the port unreachable ICMP notification.
* Sends the first packet and releases all the others.
* Releases the packet queu on error.
* @param packet The packet to be send. Input parameter.
* @param error The packet error reporting service. Prefixes the received packet. Input parameter.
*/
void udp_send_icmp_port_unreachable( packet_t packet, services_t error );
 
/** @name Socket messages processing functions
*/
/*@{*/
196,6 → 206,10
 
fibril_rwlock_initialize( & udp_globals.lock );
fibril_rwlock_write_lock( & udp_globals.lock );
udp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP );
if( udp_globals.icmp_phone < 0 ){
return udp_globals.icmp_phone;
}
udp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg );
if( udp_globals.ip_phone < 0 ){
return udp_globals.ip_phone;
209,24 → 223,12
return EOK;
}
 
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver ){
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
ERROR_DECLARE;
 
if( ERROR_OCCURRED( udp_process_packet( packet ))){
pq_release( udp_globals.net_phone, packet_get_id( packet ));
return ERROR_CODE;
}
 
return EOK;
}
 
int udp_process_packet( packet_t packet ){
ERROR_DECLARE;
 
uint8_t * src;
uint8_t * dest;
int length;
void * data;
int offset;
uint8_t * data;
udp_header_ref header;
socket_core_ref * socket;
packet_t next_packet;
234,23 → 236,55
// uint16_t checksum;
int fragments;
packet_t tmp_packet;
icmp_type_t type;
icmp_code_t code;
 
// get packet data
length = packet_get_addr( packet, & src, & dest );
if( length != sizeof( in_addr_t )) return EINVAL;
if( error ){
switch( error ){
case SERVICE_ICMP:
// process error
// TODO remove debug dump
// length = icmp_client_header_length( packet );
length = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
if( length < 0 ){
return release_and_return( packet, length );
}
printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
return release_and_return( packet, ERROR_CODE );
}
break;
default:
return release_and_return( packet, ENOTSUP );
}
}
// TODO process received ipopts?
ERROR_PROPAGATE( ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL ));
offset = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
if( offset < 0 ){
return release_and_return( packet, offset );
}
 
length = packet_get_data_length( packet );
if( length <= 0 ) return EINVAL;
if( length < sizeof( udp_header_t )) return NO_DATA;
if( length <= 0 ){
return release_and_return( packet, EINVAL );
}
if( length < sizeof( udp_header_t ) + offset ){
return release_and_return( packet, NO_DATA );
}
data = packet_get_data( packet );
if( ! data ) return NO_DATA;
if( ! data ){
return release_and_return( packet, NO_DATA );
}
// get udp header
header = ( udp_header_ref ) data;
header = ( udp_header_ref )( data + offset );
// find the destination socket
socket = socket_ports_find( & udp_globals.sockets, ntohs( header->dest ));
if( ! socket ) return EADDRNOTAVAIL;
if( ! socket ){
udp_send_icmp_port_unreachable( 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;
258,10 → 292,14
do{
++ fragments;
length = packet_get_data_length( packet );
if( ! length ) return NO_DATA;
if( ! length ){
return release_and_return( packet, NO_DATA );
}
if( total_length < length ){
// cut of the suffix if too long
ERROR_PROPAGATE( packet_trim( next_packet, 0, length - total_length ));
if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
return release_and_return( packet, ERROR_CODE );
}
// relese the rest of the packet fragments
tmp_packet = pq_next( next_packet );
while( tmp_packet ){
277,7 → 315,9
*/
}while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
// queue the received packet
ERROR_PROPAGATE( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ));
if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
return release_and_return( packet, ERROR_CODE );
}
 
// notify the destination socket
async_msg_2(( ** socket ).phone, NET_SOCKET_RECEIVED, ( ** socket ).socket_id, fragments );
294,7 → 334,7
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 );
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;
495,7 → 535,7
return ERROR_CODE;
}
// send the packet
return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP );
return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP, 0 );
// TODO IPv6
default:
return EAFNOSUPPORT;
645,5 → 685,32
return length;
}
 
static int release_and_return( packet_t packet, int result ){
pq_release( udp_globals.net_phone, packet_get_id( packet ));
return result;
}
 
void udp_send_icmp_port_unreachable( packet_t packet, services_t error ){
packet_t next;
uint8_t * src;
int length;
 
// detach the first packet and release the others
next = pq_detach( packet );
if( next ){
pq_release( udp_globals.net_phone, packet_get_id( next ));
}
length = packet_get_addr( packet, & src, NULL );
if(( length > 0 )
&& ( ! error )
&& ( udp_globals.icmp_phone >= 0 )
// set both addresses to the source one (avoids the source address deletion before setting the destination one)
&& ( packet_set_addr( packet, src, src, length ) == EOK )){
icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
}else{
return release_and_return( packet, EINVAL );
}
}
 
/** @}
*/
/branches/network/uspace/srv/net/tl/udp/Makefile
47,6 → 47,8
$(STRUCTURES)measured_strings.c \
$(NET_BASE)il/ip/ip_client.c \
$(NET_BASE)il/ip/ip_remote.c \
$(NET_BASE)il/icmp/icmp_remote.c \
$(NET_BASE)il/icmp/icmp_client.c \
$(NET_BASE)net/net_remote.c \
$(NET_BASE)socket/socket_core.c
 
/branches/network/uspace/srv/net/tl/udp/udp.h
49,24 → 49,27
/** UDP global data.
*/
struct udp_globals{
/** Networking module phone.
*/
int net_phone;
/** IP module phone.
*/
int ip_phone;
/** ICMP module phone.
*/
int icmp_phone;
/** Reserved packet prefix length.
*/
size_t prefix;
size_t prefix;
/** Maximal packet content length.
*/
size_t content;
size_t content;
/** Reserved packet suffix length.
*/
size_t suffix;
size_t suffix;
/** Packet address length.
*/
size_t addr_len;
/** Networking module phone.
*/
int net_phone;
size_t addr_len;
/** Last used free port.
*/
int last_used_port;