Ignore:
Timestamp:
2010-01-04T23:25:48Z (15 years ago)
Author:
Lukas Mejdrech <lukasmejdrech@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
eac9722
Parents:
1a0fb3f8
Message:
  • socket identifier generation moved to libsocket, + data fragment size fix and enhancement, + [ICMP|TCP|UDP]_HEADER_SIZE definition, + int_map_update() function to alter item key
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/socket/socket_client.c

    r1a0fb3f8 rede63e4  
    4040#include <async.h>
    4141#include <fibril_synch.h>
     42#include <limits.h>
     43#include <stdlib.h>
    4244
    4345#include <ipc/services.h>
     
    7476 */
    7577#define SOCKET_CONNECT_TIMEOUT  ( 1 * 1000 * 1000 )
     78
     79/** Maximum number of random attempts to find a new socket identifier before switching to the sequence.
     80 */
     81#define SOCKET_ID_TRIES                                 100
    7682
    7783/** Type definition of the socket specific data.
     
    155161         */
    156162        int     udp_phone;
     163//      /** The last socket identifier.
     164//       */
     165//      int last_id;
    157166        /** Active sockets.
    158167         */
     
    168177        .tcp_phone = -1,
    169178        .udp_phone = -1,
     179//      .last_id = 0,
    170180        .sockets = NULL,
    171181        .lock = {
     
    199209 */
    200210static sockets_ref      socket_get_sockets( void );
     211
     212/** Tries to find a new free socket identifier.
     213 *      @returns The new socket identifier.
     214 *  @returns ELIMIT if there is no socket identifier available.
     215 */
     216static int      socket_generate_new_id( void );
    201217
    202218/** Default thread for new connections.
     
    288304                        socket_globals.sockets = NULL;
    289305                }
     306                srand( task_get_id());
    290307        }
    291308        return socket_globals.sockets;
     309}
     310
     311static int socket_generate_new_id( void ){
     312        sockets_ref     sockets;
     313        int                     socket_id;
     314        int                     count;
     315
     316        sockets = socket_get_sockets();
     317        count = 0;
     318//      socket_id = socket_globals.last_id;
     319        do{
     320                if( count < SOCKET_ID_TRIES ){
     321                        socket_id = rand() % INT_MAX;
     322                        ++ count;
     323                }else if( count == SOCKET_ID_TRIES ){
     324                        socket_id = 1;
     325                        ++ count;
     326                // only this branch for last_id
     327                }else{
     328                        if( socket_id < INT_MAX ){
     329                                ++ socket_id;
     330/*                      }else if( socket_globals.last_id ){
     331*                               socket_globals.last_id = 0;
     332*                               socket_id = 1;
     333*/                      }else{
     334                                return ELIMIT;
     335                        }
     336                }
     337        }while( sockets_find( sockets, socket_id ));
     338//      last_id = socket_id
     339        return socket_id;
    292340}
    293341
     
    311359        ipc_call_t              call;
    312360        socket_ref              socket;
    313         socket_ref              new_socket;
    314361
    315362        while( true ){
     
    318365                switch( IPC_GET_METHOD( call )){
    319366                        case NET_SOCKET_RECEIVED:
    320                                 fibril_rwlock_read_lock( & socket_globals.lock );
    321                                 // find the socket
    322                                 socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call ));
    323                                 if( ! socket ){
    324                                         ERROR_CODE = ENOTSOCK;
    325                                 }else{
    326                                         fibril_mutex_lock( & socket->receive_lock );
    327                                         // push the number of received packet fragments
    328                                         if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){
    329                                                 // signal the received packet
    330                                                 fibril_condvar_signal( & socket->receive_signal );
    331                                         }
    332                                         fibril_mutex_unlock( & socket->receive_lock );
    333                                 }
    334                                 fibril_rwlock_read_unlock( & socket_globals.lock );
    335                                 break;
    336367                        case NET_SOCKET_ACCEPTED:
    337                                 fibril_rwlock_read_lock( & socket_globals.lock );
    338                                 // find the socket
    339                                 socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call ));
    340                                 if( ! socket ){
    341                                         ERROR_CODE = ENOTSOCK;
    342                                 }else{
    343                                         // create a new scoket
    344                                         new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
    345                                         if( ! new_socket ){
    346                                                 ERROR_CODE = ENOMEM;
    347                                         }else{
    348                                                 bzero( new_socket, sizeof( * new_socket ));
    349                                                 socket_initialize( new_socket, SOCKET_GET_NEW_SOCKET_ID( call ), socket->phone, socket->service );
    350                                                 ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket );
    351                                                 if( ERROR_CODE < 0 ){
    352                                                         free( new_socket );
    353                                                 }else{
    354                                                         // push the new socket identifier
    355                                                         fibril_mutex_lock( & socket->accept_lock );
    356                                                         if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, new_socket->socket_id, SOCKET_MAX_ACCEPTED_SIZE ))){
    357                                                                 sockets_exclude( socket_get_sockets(), new_socket->socket_id );
    358                                                         }else{
    359                                                                 // signal the accepted socket
    360                                                                 fibril_condvar_signal( & socket->accept_signal );
    361                                                         }
    362                                                         fibril_mutex_unlock( & socket->accept_lock );
    363                                                         ERROR_CODE = EOK;
    364                                                 }
    365                                         }
    366                                 }
    367                                 fibril_rwlock_read_unlock( & socket_globals.lock );
    368                                 break;
    369368                        case NET_SOCKET_DATA_FRAGMENT_SIZE:
    370369                                fibril_rwlock_read_lock( & socket_globals.lock );
     
    374373                                        ERROR_CODE = ENOTSOCK;
    375374                                }else{
    376                                         fibril_rwlock_write_lock( & socket->sending_lock );
    377                                         // set the data fragment size
    378                                         socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call );
    379                                         fibril_rwlock_write_unlock( & socket->sending_lock );
    380                                         ERROR_CODE = EOK;
     375                                        switch( IPC_GET_METHOD( call )){
     376                                                case NET_SOCKET_RECEIVED:
     377                                                        fibril_mutex_lock( & socket->receive_lock );
     378                                                        // push the number of received packet fragments
     379                                                        if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){
     380                                                                // signal the received packet
     381                                                                fibril_condvar_signal( & socket->receive_signal );
     382                                                        }
     383                                                        fibril_mutex_unlock( & socket->receive_lock );
     384                                                        break;
     385                                                case NET_SOCKET_ACCEPTED:
     386                                                        // push the new socket identifier
     387                                                        fibril_mutex_lock( & socket->accept_lock );
     388                                                        if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, SOCKET_GET_NEW_SOCKET_ID( call ), SOCKET_MAX_ACCEPTED_SIZE ))){
     389                                                                sockets_exclude( socket_get_sockets(), SOCKET_GET_NEW_SOCKET_ID( call ));
     390                                                        }else{
     391                                                                // signal the accepted socket
     392                                                                fibril_condvar_signal( & socket->accept_signal );
     393                                                        }
     394                                                        fibril_mutex_unlock( & socket->accept_lock );
     395                                                        break;
     396                                                default:
     397                                                        ERROR_CODE = ENOTSUP;
     398                                        }
     399                                        if(( SOCKET_GET_DATA_FRAGMENT_SIZE( call ) > 0 )
     400                                        && ( SOCKET_GET_DATA_FRAGMENT_SIZE( call ) != socket->data_fragment_size )){
     401                                                fibril_rwlock_write_lock( & socket->sending_lock );
     402                                                // set the data fragment size
     403                                                socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call );
     404                                                fibril_rwlock_write_unlock( & socket->sending_lock );
     405                                        }
    381406                                }
    382407                                fibril_rwlock_read_unlock( & socket_globals.lock );
    383                                 break;
    384408                        default:
    385409                                ERROR_CODE = ENOTSUP;
     
    396420        int                     socket_id;
    397421        services_t      service;
     422        int                     count;
    398423
    399424        // find the appropriate service
     
    437462        if( ! socket ) return ENOMEM;
    438463        bzero( socket, sizeof( * socket ));
     464        count = 0;
     465        fibril_rwlock_write_lock( & socket_globals.lock );
    439466        // request a new socket
    440         if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, 0, 0, service, ( ipcarg_t * ) & socket_id, ( ipcarg_t * ) & socket->data_fragment_size, ( ipcarg_t * ) & socket->header_size ))){
     467        socket_id = socket_generate_new_id();
     468        if( socket_id <= 0 ){
     469                fibril_rwlock_write_unlock( & socket_globals.lock );
     470                free( socket );
     471                return socket_id;
     472        }
     473        if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, socket_id, 0, service, NULL, ( ipcarg_t * ) & socket->data_fragment_size, ( ipcarg_t * ) & socket->header_size ))){
     474                fibril_rwlock_write_unlock( & socket_globals.lock );
    441475                free( socket );
    442476                return ERROR_CODE;
     
    445479        socket_initialize( socket, socket_id, phone, service );
    446480        // store the new socket
    447         fibril_rwlock_write_lock( & socket_globals.lock );
    448481        ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket );
    449482        fibril_rwlock_write_unlock( & socket_globals.lock );
     
    509542int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){
    510543        socket_ref              socket;
     544        socket_ref              new_socket;
    511545        aid_t                   message_id;
    512546        int                             result;
     
    515549        if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM;
    516550
    517         fibril_rwlock_read_lock( & socket_globals.lock );
     551        fibril_rwlock_write_lock( & socket_globals.lock );
    518552        // find the socket
    519553        socket = sockets_find( socket_get_sockets(), socket_id );
    520554        if( ! socket ){
    521                 fibril_rwlock_read_unlock( & socket_globals.lock );
     555                fibril_rwlock_write_unlock( & socket_globals.lock );
    522556                return ENOTSOCK;
    523557        }
     
    526560        ++ socket->blocked;
    527561        while( dyn_fifo_value( & socket->accepted ) <= 0 ){
    528                 fibril_rwlock_read_unlock( & socket_globals.lock );
     562                fibril_rwlock_write_unlock( & socket_globals.lock );
    529563                fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock );
    530                 fibril_rwlock_read_lock( & socket_globals.lock );
     564                fibril_rwlock_write_lock( & socket_globals.lock );
    531565        }
    532566        -- socket->blocked;
     567
     568        // create a new scoket
     569        new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
     570        if( ! new_socket ){
     571                fibril_mutex_unlock( & socket->accept_lock );
     572                fibril_rwlock_write_unlock( & socket_globals.lock );
     573                return ENOMEM;
     574        }
     575        bzero( new_socket, sizeof( * new_socket ));
     576        socket_id = socket_generate_new_id();
     577        if( socket_id <= 0 ){
     578                fibril_mutex_unlock( & socket->accept_lock );
     579                fibril_rwlock_write_unlock( & socket_globals.lock );
     580                free( new_socket );
     581                return socket_id;
     582        }
     583        socket_initialize( new_socket, socket_id, socket->phone, socket->service );
     584        result = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket );
     585        if( result < 0 ){
     586                fibril_mutex_unlock( & socket->accept_lock );
     587                fibril_rwlock_write_unlock( & socket_globals.lock );
     588                free( new_socket );
     589                return result;
     590        }
     591
    533592        // request accept
    534         message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, 0, socket->service, & answer );
     593        message_id = async_send_5( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, 0, socket->service, 0, new_socket->socket_id, & answer );
    535594        // read address
    536         async_data_read_start( socket->phone, cliaddr, * addrlen );
    537         fibril_rwlock_read_unlock( & socket_globals.lock );
     595        ipc_data_read_start( socket->phone, cliaddr, * addrlen );
     596        fibril_rwlock_write_unlock( & socket_globals.lock );
    538597        async_wait_for( message_id, ( ipcarg_t * ) & result );
    539598        if( result > 0 ){
     599                if( result != socket_id ){
     600                        result = EINVAL;
     601                }
    540602                // dequeue the accepted socket if successful
    541603                dyn_fifo_pop( & socket->accepted );
    542604                // set address length
    543605                * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer );
     606                new_socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer );
    544607        }else if( result == ENOTSOCK ){
    545608                // empty the queue if no accepted sockets
     
    609672        ipcarg_t                result;
    610673        size_t                  fragments;
     674        ipc_call_t              answer;
    611675
    612676        if( ! data ) return EBADMEM;
     
    621685        fibril_rwlock_read_lock( & socket->sending_lock );
    622686        // compute data fragment count
    623         fragments = ( datalength + socket->header_size ) / socket->data_fragment_size;
    624         if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments;
     687        if( socket->data_fragment_size > 0 ){
     688                fragments = ( datalength + socket->header_size ) / socket->data_fragment_size;
     689                if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments;
     690        }else{
     691                fragments = 1;
     692        }
    625693        // request send
    626         message_id = async_send_5( socket->phone, message, ( ipcarg_t ) socket->socket_id, socket->data_fragment_size, socket->service, ( ipcarg_t ) flags, fragments, NULL );
     694        message_id = async_send_5( socket->phone, message, ( ipcarg_t ) socket->socket_id, ( fragments == 1 ? datalength : socket->data_fragment_size ), socket->service, ( ipcarg_t ) flags, fragments, & answer );
    627695        // send the address if given
    628696        if(( ! toaddr ) || ( async_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){
     
    643711                }
    644712        }
     713        async_wait_for( message_id, & result );
     714        if(( SOCKET_GET_DATA_FRAGMENT_SIZE( answer ) > 0 )
     715        && ( SOCKET_GET_DATA_FRAGMENT_SIZE( answer ) != socket->data_fragment_size )){
     716                // set the data fragment size
     717                socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer );
     718        }
    645719        fibril_rwlock_read_unlock( & socket->sending_lock );
    646720        fibril_rwlock_read_unlock( & socket_globals.lock );
    647         async_wait_for( message_id, & result );
    648721        return ( int ) result;
    649722}
Note: See TracChangeset for help on using the changeset viewer.