Changeset 7715994 in mainline for uspace/srv/net/tl/udp/udp.c


Ignore:
Timestamp:
2010-03-13T12:17:02Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6ba20a6b
Parents:
d0febca (diff), 2070570 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/udp/udp.c

    rd0febca r7715994  
    104104 *  @returns Other error codes as defined for the udp_process_packet() function.
    105105 */
    106 int     udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
     106int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
    107107
    108108/** Processes the received UDP packet queue.
     
    121121 *  @returns Other error codes as defined for the ip_client_process_packet() function.
    122122 */
    123 int udp_process_packet( device_id_t device_id, packet_t packet, services_t error );
     123int udp_process_packet(device_id_t device_id, packet_t packet, services_t error);
    124124
    125125/** Releases the packet and returns the result.
     
    128128 *  @return The result parameter.
    129129 */
    130 int     udp_release_and_return( packet_t packet, int result );
     130int udp_release_and_return(packet_t packet, int result);
    131131
    132132/** @name Socket messages processing functions
     
    141141 *  @see socket.h
    142142 */
    143 int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
     143int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    144144
    145145/** Sends data from the socket to the remote address.
     
    164164 *  @returns Other error codes as defined for the ip_send_msg() function.
    165165 */
    166 int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags );
     166int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags);
    167167
    168168/** Receives data to the socket.
     
    181181 *  @returns Other error codes as defined for the data_reply() function.
    182182 */
    183 int     udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
     183int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen);
    184184
    185185/*@}*/
     
    189189udp_globals_t   udp_globals;
    190190
    191 int udp_initialize( async_client_conn_t client_connection ){
     191int udp_initialize(async_client_conn_t client_connection){
    192192        ERROR_DECLARE;
    193193
    194         measured_string_t       names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }, { "UDP_AUTOBINDING", 15 }};
    195         measured_string_ref     configuration;
    196         size_t                          count = sizeof( names ) / sizeof( measured_string_t );
    197         char *                          data;
    198 
    199         fibril_rwlock_initialize( & udp_globals.lock );
    200         fibril_rwlock_write_lock( & udp_globals.lock );
    201         udp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP, ICMP_CONNECT_TIMEOUT );
    202         udp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg );
    203         if( udp_globals.ip_phone < 0 ){
     194        measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}};
     195        measured_string_ref configuration;
     196        size_t count = sizeof(names) / sizeof(measured_string_t);
     197        char * data;
     198
     199        fibril_rwlock_initialize(&udp_globals.lock);
     200        fibril_rwlock_write_lock(&udp_globals.lock);
     201        udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
     202        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg);
     203        if(udp_globals.ip_phone < 0){
    204204                return udp_globals.ip_phone;
    205205        }
    206206        // read default packet dimensions
    207         ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension ));
    208         ERROR_PROPAGATE( socket_ports_initialize( & udp_globals.sockets ));
    209         if( ERROR_OCCURRED( packet_dimensions_initialize( & udp_globals.dimensions ))){
    210                 socket_ports_destroy( & udp_globals.sockets );
     207        ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
     208        ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets));
     209        if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){
     210                socket_ports_destroy(&udp_globals.sockets);
    211211                return ERROR_CODE;
    212212        }
    213         udp_globals.packet_dimension.prefix += sizeof( udp_header_t );
    214         udp_globals.packet_dimension.content -= sizeof( udp_header_t );
     213        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
     214        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    215215        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    216216        // get configuration
    217217        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    218218        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
    219         configuration = & names[ 0 ];
    220         ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data ));
    221         if( configuration ){
    222                 if( configuration[ 0 ].value ){
    223                         udp_globals.checksum_computing = ( configuration[ 0 ].value[ 0 ] == 'y' );
    224                 }
    225                 if( configuration[ 1 ].value ){
    226                         udp_globals.autobinding = ( configuration[ 1 ].value[ 0 ] == 'y' );
    227                 }
    228                 net_free_settings( configuration, data );
    229         }
    230         fibril_rwlock_write_unlock( & udp_globals.lock );
     219        configuration = &names[0];
     220        ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, count, &data));
     221        if(configuration){
     222                if(configuration[0].value){
     223                        udp_globals.checksum_computing = (configuration[0].value[0] == 'y');
     224                }
     225                if(configuration[1].value){
     226                        udp_globals.autobinding = (configuration[1].value[0] == 'y');
     227                }
     228                net_free_settings(configuration, data);
     229        }
     230        fibril_rwlock_write_unlock(&udp_globals.lock);
    231231        return EOK;
    232232}
    233233
    234 int     udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
    235         int     result;
    236 
    237         fibril_rwlock_write_lock( & udp_globals.lock );
    238         result = udp_process_packet( device_id, packet, error );
    239         if( result != EOK ){
    240                 fibril_rwlock_write_unlock( & udp_globals.lock );
     234int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
     235        int result;
     236
     237        fibril_rwlock_write_lock(&udp_globals.lock);
     238        result = udp_process_packet(device_id, packet, error);
     239        if(result != EOK){
     240                fibril_rwlock_write_unlock(&udp_globals.lock);
    241241        }
    242242
     
    244244}
    245245
    246 int udp_process_packet( device_id_t device_id, packet_t packet, services_t error ){
     246int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){
    247247        ERROR_DECLARE;
    248248
    249         size_t                  length;
    250         size_t                  offset;
    251         int                             result;
    252         udp_header_ref  header;
    253         socket_core_ref socket;
    254         packet_t                next_packet;
    255         size_t                  total_length;
    256         uint32_t                checksum;
    257         int                             fragments;
    258         packet_t                tmp_packet;
    259         icmp_type_t             type;
    260         icmp_code_t             code;
    261         ip_pseudo_header_ref    ip_header;
    262         struct sockaddr *               src;
    263         struct sockaddr *               dest;
    264         packet_dimension_ref    packet_dimension;
    265 
    266         if( error ){
    267                 switch( error ){
     249        size_t length;
     250        size_t offset;
     251        int result;
     252        udp_header_ref header;
     253        socket_core_ref socket;
     254        packet_t next_packet;
     255        size_t total_length;
     256        uint32_t checksum;
     257        int fragments;
     258        packet_t tmp_packet;
     259        icmp_type_t type;
     260        icmp_code_t code;
     261        ip_pseudo_header_ref ip_header;
     262        struct sockaddr * src;
     263        struct sockaddr * dest;
     264        packet_dimension_ref packet_dimension;
     265
     266        if(error){
     267                switch(error){
    268268                        case SERVICE_ICMP:
    269269                                // ignore error
    270                                 // length = icmp_client_header_length( packet );
     270                                // length = icmp_client_header_length(packet);
    271271                                // process error
    272                                 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
    273                                 if( result < 0 ){
    274                                         return udp_release_and_return( packet, result );
     272                                result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     273                                if(result < 0){
     274                                        return udp_release_and_return(packet, result);
    275275                                }
    276                                 length = ( size_t ) result;
    277                                 if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
    278                                         return udp_release_and_return( packet, ERROR_CODE );
     276                                length = (size_t) result;
     277                                if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
     278                                        return udp_release_and_return(packet, ERROR_CODE);
    279279                                }
    280280                                break;
    281281                        default:
    282                                 return udp_release_and_return( packet, ENOTSUP );
     282                                return udp_release_and_return(packet, ENOTSUP);
    283283                }
    284284        }
    285285        // TODO process received ipopts?
    286         result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
    287         if( result < 0 ){
    288                 return udp_release_and_return( packet, result );
    289         }
    290         offset = ( size_t ) result;
    291 
    292         length = packet_get_data_length( packet );
    293         if( length <= 0 ){
    294                 return udp_release_and_return( packet, EINVAL );
    295         }
    296         if( length < UDP_HEADER_SIZE + offset ){
    297                 return udp_release_and_return( packet, NO_DATA );
     286        result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
     287        if(result < 0){
     288                return udp_release_and_return(packet, result);
     289        }
     290        offset = (size_t) result;
     291
     292        length = packet_get_data_length(packet);
     293        if(length <= 0){
     294                return udp_release_and_return(packet, EINVAL);
     295        }
     296        if(length < UDP_HEADER_SIZE + offset){
     297                return udp_release_and_return(packet, NO_DATA);
    298298        }
    299299
    300300        // trim all but UDP header
    301         if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){
    302                 return udp_release_and_return( packet, ERROR_CODE );
     301        if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
     302                return udp_release_and_return(packet, ERROR_CODE);
    303303        }
    304304
    305305        // get udp header
    306         header = ( udp_header_ref ) packet_get_data( packet );
    307         if( ! header ){
    308                 return udp_release_and_return( packet, NO_DATA );
     306        header = (udp_header_ref) packet_get_data(packet);
     307        if(! header){
     308                return udp_release_and_return(packet, NO_DATA);
    309309        }
    310310        // find the destination socket
    311         socket = socket_port_find( & udp_globals.sockets, ntohs( header->destination_port ), SOCKET_MAP_KEY_LISTENING, 0 );
    312         if( ! socket ){
    313                 if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){
    314                         icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
     311        socket = socket_port_find(&udp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     312        if(! socket){
     313                if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
     314                        icmp_destination_unreachable_msg(udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet);
    315315                }
    316316                return EADDRNOTAVAIL;
     
    320320        next_packet = packet;
    321321        fragments = 0;
    322         total_length = ntohs( header->total_length );
     322        total_length = ntohs(header->total_length);
    323323        // compute header checksum if set
    324         if( header->checksum && ( ! error )){
    325                 result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
    326                 if( result <= 0 ){
    327                         return udp_release_and_return( packet, result );
    328                 }
    329                 if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_UDP, src, result, dest, result, total_length, & ip_header, & length ))){
    330                         return udp_release_and_return( packet, ERROR_CODE );
     324        if(header->checksum && (! error)){
     325                result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     326                if(result <= 0){
     327                        return udp_release_and_return(packet, result);
     328                }
     329                if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){
     330                        return udp_release_and_return(packet, ERROR_CODE);
    331331                }else{
    332                         checksum = compute_checksum( 0, ip_header, length );
     332                        checksum = compute_checksum(0, ip_header, length);
    333333                        // the udp header checksum will be added with the first fragment later
    334                         free( ip_header );
     334                        free(ip_header);
    335335                }
    336336        }else{
     
    341341        do{
    342342                ++ fragments;
    343                 length = packet_get_data_length( next_packet );
    344                 if( length <= 0 ){
    345                         return udp_release_and_return( packet, NO_DATA );
    346                 }
    347                 if( total_length < length ){
    348                         if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
    349                                 return udp_release_and_return( packet, ERROR_CODE );
     343                length = packet_get_data_length(next_packet);
     344                if(length <= 0){
     345                        return udp_release_and_return(packet, NO_DATA);
     346                }
     347                if(total_length < length){
     348                        if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - total_length))){
     349                                return udp_release_and_return(packet, ERROR_CODE);
    350350                        }
    351351                        // add partial checksum if set
    352                         if( header->checksum ){
    353                                 checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
     352                        if(header->checksum){
     353                                checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
    354354                        }
    355355                        // relese the rest of the packet fragments
    356                         tmp_packet = pq_next( next_packet );
    357                         while( tmp_packet ){
    358                                 next_packet = pq_detach( tmp_packet );
    359                                 pq_release( udp_globals.net_phone, packet_get_id( tmp_packet ));
     356                        tmp_packet = pq_next(next_packet);
     357                        while(tmp_packet){
     358                                next_packet = pq_detach(tmp_packet);
     359                                pq_release(udp_globals.net_phone, packet_get_id(tmp_packet));
    360360                                tmp_packet = next_packet;
    361361                        }
     
    365365                total_length -= length;
    366366                // add partial checksum if set
    367                 if( header->checksum ){
    368                         checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
    369                 }
    370         }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
     367                if(header->checksum){
     368                        checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
     369                }
     370        }while((next_packet = pq_next(next_packet)) && (total_length > 0));
    371371
    372372        // check checksum
    373         if( header->checksum ){
    374                 if( flip_checksum( compact_checksum( checksum )) != IP_CHECKSUM_ZERO ){
    375                         if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){
     373        if(header->checksum){
     374                if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){
     375                        if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
    376376                                // checksum error ICMP
    377                                 icmp_parameter_problem_msg( udp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet );
     377                                icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
    378378                        }
    379379                        return EINVAL;
     
    382382
    383383        // queue the received packet
    384         if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))
    385         || ERROR_OCCURRED( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension ))){
    386                 return udp_release_and_return( packet, ERROR_CODE );
     384        if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE))
     385                || ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension))){
     386                return udp_release_and_return(packet, ERROR_CODE);
    387387        }
    388388
    389389        // notify the destination socket
    390         fibril_rwlock_write_unlock( & udp_globals.lock );
    391         async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, packet_dimension->content, 0, 0, ( ipcarg_t ) fragments );
    392 /*      fibril_rwlock_write_unlock( & udp_globals.lock );
    393         async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments );
    394 */      return EOK;
    395 }
    396 
    397 int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
     390        fibril_rwlock_write_unlock(&udp_globals.lock);
     391        async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments);
     392        return EOK;
     393}
     394
     395int udp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    398396        ERROR_DECLARE;
    399397
    400         packet_t        packet;
    401 
    402         * answer_count = 0;
    403         switch( IPC_GET_METHOD( * call )){
     398        packet_t packet;
     399
     400        *answer_count = 0;
     401        switch(IPC_GET_METHOD(*call)){
    404402                case NET_TL_RECEIVED:
    405                         if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    406                                 ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
     403                        if(! ERROR_OCCURRED(packet_translate(udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     404                                ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_UDP, IPC_GET_ERROR(call));
    407405                        }
    408406                        return ERROR_CODE;
    409407                case IPC_M_CONNECT_TO_ME:
    410                         return udp_process_client_messages( callid, * call );
     408                        return udp_process_client_messages(callid, * call);
    411409        }
    412410        return ENOTSUP;
    413411}
    414412
    415 int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
    416         int                                             res;
    417         bool                                    keep_on_going = true;
    418         socket_cores_t                  local_sockets;
    419         int                                             app_phone = IPC_GET_PHONE( & call );
    420         struct sockaddr *               addr;
    421         size_t                                  addrlen;
    422         fibril_rwlock_t                 lock;
    423         ipc_call_t                              answer;
    424         int                                             answer_count;
    425         packet_dimension_ref    packet_dimension;
     413int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
     414        int res;
     415        bool keep_on_going = true;
     416        socket_cores_t local_sockets;
     417        int app_phone = IPC_GET_PHONE(&call);
     418        struct sockaddr * addr;
     419        size_t addrlen;
     420        ipc_call_t answer;
     421        int answer_count;
     422        packet_dimension_ref packet_dimension;
    426423
    427424        /*
     
    429426         *  - Answer the first IPC_M_CONNECT_TO_ME call.
    430427         */
    431         ipc_answer_0( callid, EOK );
     428        res = EOK;
     429        answer_count = 0;
    432430
    433431        // The client connection is only in one fibril and therefore no additional locks are needed.
    434432
    435         socket_cores_initialize( & local_sockets );
    436         fibril_rwlock_initialize( & lock );
    437 
    438         while( keep_on_going ){
     433        socket_cores_initialize(&local_sockets);
     434
     435        while(keep_on_going){
     436
     437                // answer the call
     438                answer_call(callid, res, &answer, answer_count);
     439
    439440                // refresh data
    440                 refresh_answer( & answer, & answer_count );
    441 
    442                 callid = async_get_call( & call );
    443 //              printf( "message %d\n", IPC_GET_METHOD( * call ));
    444 
    445                 switch( IPC_GET_METHOD( call )){
     441                refresh_answer(&answer, &answer_count);
     442
     443                // get the next call
     444                callid = async_get_call(&call);
     445
     446                // process the call
     447                switch(IPC_GET_METHOD(call)){
    446448                        case IPC_M_PHONE_HUNGUP:
    447449                                keep_on_going = false;
    448                                 res = EOK;
     450                                res = EHANGUP;
    449451                                break;
    450452                        case NET_SOCKET:
    451                                 fibril_rwlock_write_lock( & lock );
    452                                 * SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call );
    453                                 res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer ));
    454                                 fibril_rwlock_write_unlock( & lock );
    455                                 if( res == EOK ){
    456                                         if( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){
    457                                                 * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = packet_dimension->content;
     453                                *SOCKET_SET_SOCKET_ID(answer) = SOCKET_GET_SOCKET_ID(call);
     454                                res = socket_create(&local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID(answer));
     455                                if(res == EOK){
     456                                        if(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
     457                                                *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = packet_dimension->content;
    458458                                        }
    459 //                                      * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
    460                                         * SOCKET_SET_HEADER_SIZE( answer ) = UDP_HEADER_SIZE;
     459//                                      *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = MAX_UDP_FRAGMENT_SIZE;
     460                                        *SOCKET_SET_HEADER_SIZE(answer) = UDP_HEADER_SIZE;
    461461                                        answer_count = 3;
    462462                                }
    463463                                break;
    464464                        case NET_SOCKET_BIND:
    465                                 res = data_receive(( void ** ) & addr, & addrlen );
    466                                 if( res == EOK ){
    467                                         fibril_rwlock_read_lock( & lock );
    468                                         fibril_rwlock_write_lock( & udp_globals.lock );
    469                                         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 );
    470                                         fibril_rwlock_write_unlock( & udp_globals.lock );
    471                                         fibril_rwlock_read_unlock( & lock );
    472                                         free( addr );
     465                                res = data_receive((void **) &addr, &addrlen);
     466                                if(res == EOK){
     467                                        fibril_rwlock_write_lock(&udp_globals.lock);
     468                                        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);
     469                                        fibril_rwlock_write_unlock(&udp_globals.lock);
     470                                        free(addr);
    473471                                }
    474472                                break;
    475473                        case NET_SOCKET_SENDTO:
    476                                 res = data_receive(( void ** ) & addr, & addrlen );
    477                                 if( res == EOK ){
    478                                         fibril_rwlock_read_lock( & lock );
    479                                         fibril_rwlock_write_lock( & udp_globals.lock );
    480                                         res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
    481                                         if( res != EOK ){
    482                                                 fibril_rwlock_write_unlock( & udp_globals.lock );
     474                                res = data_receive((void **) &addr, &addrlen);
     475                                if(res == EOK){
     476                                        fibril_rwlock_write_lock(&udp_globals.lock);
     477                                        res = udp_sendto_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS(call), SOCKET_SET_DATA_FRAGMENT_SIZE(answer), SOCKET_GET_FLAGS(call));
     478                                        if(res != EOK){
     479                                                fibril_rwlock_write_unlock(&udp_globals.lock);
    483480                                        }else{
    484481                                                answer_count = 2;
    485482                                        }
    486                                         fibril_rwlock_read_unlock( & lock );
    487                                         free( addr );
     483                                        free(addr);
    488484                                }
    489485                                break;
    490486                        case NET_SOCKET_RECVFROM:
    491                                 fibril_rwlock_read_lock( & lock );
    492                                 fibril_rwlock_write_lock( & udp_globals.lock );
    493                                 res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen );
    494                                 fibril_rwlock_write_unlock( & udp_globals.lock );
    495                                 fibril_rwlock_read_unlock( & lock );
    496                                 if( res > 0 ){
    497                                         * SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
    498                                         * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
     487                                fibril_rwlock_write_lock(&udp_globals.lock);
     488                                res = udp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen);
     489                                fibril_rwlock_write_unlock(&udp_globals.lock);
     490                                if(res > 0){
     491                                        *SOCKET_SET_READ_DATA_LENGTH(answer) = res;
     492                                        *SOCKET_SET_ADDRESS_LENGTH(answer) = addrlen;
    499493                                        answer_count = 3;
    500494                                        res = EOK;
     
    502496                                break;
    503497                        case NET_SOCKET_CLOSE:
    504                                 fibril_rwlock_write_lock( & lock );
    505                                 fibril_rwlock_write_lock( & udp_globals.lock );
    506                                 res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets, NULL );
    507                                 fibril_rwlock_write_unlock( & udp_globals.lock );
    508                                 fibril_rwlock_write_unlock( & lock );
     498                                fibril_rwlock_write_lock(&udp_globals.lock);
     499                                res = socket_destroy(udp_globals.net_phone, SOCKET_GET_SOCKET_ID(call), &local_sockets, &udp_globals.sockets, NULL);
     500                                fibril_rwlock_write_unlock(&udp_globals.lock);
    509501                                break;
    510502                        case NET_SOCKET_GETSOCKOPT:
     
    514506                                break;
    515507                }
    516 
    517 //              printf( "res = %d\n", res );
    518 
    519                 answer_call( callid, res, & answer, answer_count );
    520         }
     508        }
     509
     510        // release the application phone
     511        ipc_hangup(app_phone);
    521512
    522513        // release all local sockets
    523         socket_cores_release( udp_globals.net_phone, & local_sockets, & udp_globals.sockets, NULL );
    524 
    525         return EOK;
    526 }
    527 
    528 int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags ){
     514        socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL);
     515
     516        return res;
     517}
     518
     519int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags){
    529520        ERROR_DECLARE;
    530521
    531         socket_core_ref                 socket;
    532         packet_t                                packet;
    533         packet_t                                next_packet;
    534         udp_header_ref                  header;
    535         int                                             index;
    536         size_t                                  total_length;
    537         int                                             result;
    538         uint16_t                                dest_port;
    539         uint32_t                                checksum;
    540         ip_pseudo_header_ref    ip_header;
    541         size_t                                  headerlen;
    542         device_id_t                             device_id;
    543         packet_dimension_ref    packet_dimension;
    544 
    545         ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & dest_port ));
    546 
    547         socket = socket_cores_find( local_sockets, socket_id );
    548         if( ! socket ) return ENOTSOCK;
    549 
    550         if(( socket->port <= 0 ) && udp_globals.autobinding ){
     522        socket_core_ref socket;
     523        packet_t packet;
     524        packet_t next_packet;
     525        udp_header_ref header;
     526        int index;
     527        size_t total_length;
     528        int result;
     529        uint16_t dest_port;
     530        uint32_t checksum;
     531        ip_pseudo_header_ref ip_header;
     532        size_t headerlen;
     533        device_id_t device_id;
     534        packet_dimension_ref packet_dimension;
     535
     536        ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port));
     537
     538        socket = socket_cores_find(local_sockets, socket_id);
     539        if(! socket){
     540                return ENOTSOCK;
     541        }
     542
     543        if((socket->port <= 0) && udp_globals.autobinding){
    551544                // bind the socket to a random free port if not bound
    552545//              do{
    553546                        // try to find a free port
    554 //                      fibril_rwlock_read_unlock( & udp_globals.lock );
    555 //                      fibril_rwlock_write_lock( & udp_globals.lock );
     547//                      fibril_rwlock_read_unlock(&udp_globals.lock);
     548//                      fibril_rwlock_write_lock(&udp_globals.lock);
    556549                        // might be changed in the meantime
    557 //                      if( socket->port <= 0 ){
    558                                 if( ERROR_OCCURRED( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ))){
    559 //                                      fibril_rwlock_write_unlock( & udp_globals.lock );
    560 //                                      fibril_rwlock_read_lock( & udp_globals.lock );
     550//                      if(socket->port <= 0){
     551                                if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){
     552//                                      fibril_rwlock_write_unlock(&udp_globals.lock);
     553//                                      fibril_rwlock_read_lock(&udp_globals.lock);
    561554                                        return ERROR_CODE;
    562555                                }
     
    564557                                udp_globals.last_used_port = socket->port;
    565558//                      }
    566 //                      fibril_rwlock_write_unlock( & udp_globals.lock );
    567 //                      fibril_rwlock_read_lock( & udp_globals.lock );
     559//                      fibril_rwlock_write_unlock(&udp_globals.lock);
     560//                      fibril_rwlock_read_lock(&udp_globals.lock);
    568561                        // might be changed in the meantime
    569 //              }while( socket->port <= 0 );
    570         }
    571 
    572         if( udp_globals.checksum_computing ){
    573                 if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
    574                         return udp_release_and_return( packet, ERROR_CODE );
     562//              }while(socket->port <= 0);
     563        }
     564
     565        if(udp_globals.checksum_computing){
     566                if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){
     567                        return udp_release_and_return(packet, ERROR_CODE);
    575568                }
    576569                // get the device packet dimension
    577 //              ERROR_PROPAGATE( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension ));
     570//              ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension));
    578571        }
    579572//      }else{
    580573                // do not ask all the time
    581                 ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension ));
    582                 packet_dimension = & udp_globals.packet_dimension;
     574                ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
     575                packet_dimension = &udp_globals.packet_dimension;
    583576//      }
    584577
    585578        // read the first packet fragment
    586         result = tl_socket_read_packet_data( udp_globals.net_phone, & packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen );
    587         if( result < 0 ) return result;
    588         total_length = ( size_t ) result;
    589         if( udp_globals.checksum_computing ){
    590                 checksum = compute_checksum( 0, packet_get_data( packet ), packet_get_data_length( packet ));
     579        result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
     580        if(result < 0){
     581                return result;
     582        }
     583        total_length = (size_t) result;
     584        if(udp_globals.checksum_computing){
     585                checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet));
    591586        }else{
    592587                checksum = 0;
    593588        }
    594589        // prefix the udp header
    595         header = PACKET_PREFIX( packet, udp_header_t );
    596         if( ! header ){
    597                 return udp_release_and_return( packet, ENOMEM );
    598         }
    599         bzero( header, sizeof( * header ));
     590        header = PACKET_PREFIX(packet, udp_header_t);
     591        if(! header){
     592                return udp_release_and_return(packet, ENOMEM);
     593        }
     594        bzero(header, sizeof(*header));
    600595        // read the rest of the packet fragments
    601         for( index = 1; index < fragments; ++ index ){
    602                 result = tl_socket_read_packet_data( udp_globals.net_phone, & next_packet, 0, packet_dimension, addr, addrlen );
    603                 if( result < 0 ){
    604                         return udp_release_and_return( packet, result );
    605                 }
    606                 if( ERROR_OCCURRED( pq_add( & packet, next_packet, index, 0 ))){
    607                         return udp_release_and_return( packet, ERROR_CODE );
    608                 }
    609                 total_length += ( size_t ) result;
    610                 if( udp_globals.checksum_computing ){
    611                         checksum = compute_checksum( checksum, packet_get_data( next_packet ), packet_get_data_length( next_packet ));
     596        for(index = 1; index < fragments; ++ index){
     597                result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen);
     598                if(result < 0){
     599                        return udp_release_and_return(packet, result);
     600                }
     601                if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){
     602                        return udp_release_and_return(packet, ERROR_CODE);
     603                }
     604                total_length += (size_t) result;
     605                if(udp_globals.checksum_computing){
     606                        checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet));
    612607                }
    613608        }
    614609        // set the udp header
    615         header->source_port = htons(( socket->port > 0 ) ? socket->port : 0 );
    616         header->destination_port = htons( dest_port );
    617         header->total_length = htons( total_length + sizeof( * header ));
     610        header->source_port = htons((socket->port > 0) ? socket->port : 0);
     611        header->destination_port = htons(dest_port);
     612        header->total_length = htons(total_length + sizeof(*header));
    618613        header->checksum = 0;
    619         if( udp_globals.checksum_computing ){
    620 //              if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
    621 //                      return udp_release_and_return( packet, ERROR_CODE );
    622 //              }
    623                 if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
    624                         free( ip_header );
    625                         return udp_release_and_return( packet, ERROR_CODE );
    626                 }
    627                 checksum = compute_checksum( checksum, ip_header, headerlen );
    628                 checksum = compute_checksum( checksum, ( uint8_t * ) header, sizeof( * header ));
    629                 header->checksum = htons( flip_checksum( compact_checksum( checksum )));
    630                 free( ip_header );
     614        if(udp_globals.checksum_computing){
     615                // update the pseudo header
     616                if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
     617                        free(ip_header);
     618                        return udp_release_and_return(packet, ERROR_CODE);
     619                }
     620                // finish the checksum computation
     621                checksum = compute_checksum(checksum, ip_header, headerlen);
     622                checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header));
     623                header->checksum = htons(flip_checksum(compact_checksum(checksum)));
     624                free(ip_header);
    631625        }else{
    632626                device_id = DEVICE_INVALID_ID;
    633627        }
    634628        // prepare the first packet fragment
    635         if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){
    636                 return udp_release_and_return( packet, ERROR_CODE );
     629        if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){
     630                return udp_release_and_return(packet, ERROR_CODE);
    637631        }
    638632        // send the packet
    639         fibril_rwlock_write_unlock( & udp_globals.lock );
    640         ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0 );
     633        fibril_rwlock_write_unlock(&udp_globals.lock);
     634        ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
    641635        return EOK;
    642636}
    643637
    644 int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){
     638int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
    645639        ERROR_DECLARE;
    646640
    647         socket_core_ref socket;
    648         int                             packet_id;
    649         packet_t                packet;
    650         udp_header_ref  header;
    651         struct sockaddr *       addr;
    652         size_t                  length;
    653         uint8_t *               data;
    654         int                             result;
     641        socket_core_ref socket;
     642        int packet_id;
     643        packet_t packet;
     644        udp_header_ref header;
     645        struct sockaddr * addr;
     646        size_t length;
     647        uint8_t * data;
     648        int result;
    655649
    656650        // find the socket
    657         socket = socket_cores_find( local_sockets, socket_id );
    658         if( ! socket ) return ENOTSOCK;
     651        socket = socket_cores_find(local_sockets, socket_id);
     652        if(! socket){
     653                return ENOTSOCK;
     654        }
    659655        // get the next received packet
    660         packet_id = dyn_fifo_value( & socket->received );
    661         if( packet_id < 0 ) return NO_DATA;
    662         ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, packet_id ));
     656        packet_id = dyn_fifo_value(&socket->received);
     657        if(packet_id < 0){
     658                return NO_DATA;
     659        }
     660        ERROR_PROPAGATE(packet_translate(udp_globals.net_phone, &packet, packet_id));
    663661        // get udp header
    664         data = packet_get_data( packet );
    665         if( ! data ){
    666                 pq_release( udp_globals.net_phone, packet_id );
     662        data = packet_get_data(packet);
     663        if(! data){
     664                pq_release(udp_globals.net_phone, packet_id);
    667665                return NO_DATA;
    668666        }
    669         header = ( udp_header_ref ) data;
     667        header = (udp_header_ref) data;
    670668
    671669        // set the source address port
    672         result = packet_get_addr( packet, ( uint8_t ** ) & addr, NULL );
    673         if( ERROR_OCCURRED( tl_set_address_port( addr, result, ntohs( header->source_port )))){
    674                 pq_release( udp_globals.net_phone, packet_id );
     670        result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
     671        if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){
     672                pq_release(udp_globals.net_phone, packet_id);
    675673                return ERROR_CODE;
    676674        }
    677         * addrlen = ( size_t ) result;
     675        *addrlen = (size_t) result;
    678676        // send the source address
    679         ERROR_PROPAGATE( data_reply( addr, * addrlen ));
     677        ERROR_PROPAGATE(data_reply(addr, * addrlen));
    680678
    681679        // trim the header
    682         ERROR_PROPAGATE( packet_trim( packet, UDP_HEADER_SIZE, 0 ));
     680        ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));
    683681
    684682        // reply the packets
    685         ERROR_PROPAGATE( socket_reply_packets( packet, & length ));
     683        ERROR_PROPAGATE(socket_reply_packets(packet, &length));
    686684
    687685        // release the packet
    688         dyn_fifo_pop( & socket->received );
    689         pq_release( udp_globals.net_phone, packet_get_id( packet ));
     686        dyn_fifo_pop(&socket->received);
     687        pq_release(udp_globals.net_phone, packet_get_id(packet));
    690688        // return the total length
    691         return ( int ) length;
    692 }
    693 
    694 int     udp_release_and_return( packet_t packet, int result ){
    695         pq_release( udp_globals.net_phone, packet_get_id( packet ));
     689        return (int) length;
     690}
     691
     692int udp_release_and_return(packet_t packet, int result){
     693        pq_release(udp_globals.net_phone, packet_get_id(packet));
    696694        return result;
    697695}
Note: See TracChangeset for help on using the changeset viewer.