Changeset ede63e4 in mainline for uspace/srv/net/socket/socket_client.c
- Timestamp:
- 2010-01-04T23:25:48Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- eac9722
- Parents:
- 1a0fb3f8
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/socket/socket_client.c
r1a0fb3f8 rede63e4 40 40 #include <async.h> 41 41 #include <fibril_synch.h> 42 #include <limits.h> 43 #include <stdlib.h> 42 44 43 45 #include <ipc/services.h> … … 74 76 */ 75 77 #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 76 82 77 83 /** Type definition of the socket specific data. … … 155 161 */ 156 162 int udp_phone; 163 // /** The last socket identifier. 164 // */ 165 // int last_id; 157 166 /** Active sockets. 158 167 */ … … 168 177 .tcp_phone = -1, 169 178 .udp_phone = -1, 179 // .last_id = 0, 170 180 .sockets = NULL, 171 181 .lock = { … … 199 209 */ 200 210 static 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 */ 216 static int socket_generate_new_id( void ); 201 217 202 218 /** Default thread for new connections. … … 288 304 socket_globals.sockets = NULL; 289 305 } 306 srand( task_get_id()); 290 307 } 291 308 return socket_globals.sockets; 309 } 310 311 static 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; 292 340 } 293 341 … … 311 359 ipc_call_t call; 312 360 socket_ref socket; 313 socket_ref new_socket;314 361 315 362 while( true ){ … … 318 365 switch( IPC_GET_METHOD( call )){ 319 366 case NET_SOCKET_RECEIVED: 320 fibril_rwlock_read_lock( & socket_globals.lock );321 // find the socket322 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 fragments328 if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){329 // signal the received packet330 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;336 367 case NET_SOCKET_ACCEPTED: 337 fibril_rwlock_read_lock( & socket_globals.lock );338 // find the socket339 socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call ));340 if( ! socket ){341 ERROR_CODE = ENOTSOCK;342 }else{343 // create a new scoket344 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 identifier355 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 socket360 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;369 368 case NET_SOCKET_DATA_FRAGMENT_SIZE: 370 369 fibril_rwlock_read_lock( & socket_globals.lock ); … … 374 373 ERROR_CODE = ENOTSOCK; 375 374 }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 } 381 406 } 382 407 fibril_rwlock_read_unlock( & socket_globals.lock ); 383 break;384 408 default: 385 409 ERROR_CODE = ENOTSUP; … … 396 420 int socket_id; 397 421 services_t service; 422 int count; 398 423 399 424 // find the appropriate service … … 437 462 if( ! socket ) return ENOMEM; 438 463 bzero( socket, sizeof( * socket )); 464 count = 0; 465 fibril_rwlock_write_lock( & socket_globals.lock ); 439 466 // 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 ); 441 475 free( socket ); 442 476 return ERROR_CODE; … … 445 479 socket_initialize( socket, socket_id, phone, service ); 446 480 // store the new socket 447 fibril_rwlock_write_lock( & socket_globals.lock );448 481 ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket ); 449 482 fibril_rwlock_write_unlock( & socket_globals.lock ); … … 509 542 int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ 510 543 socket_ref socket; 544 socket_ref new_socket; 511 545 aid_t message_id; 512 546 int result; … … 515 549 if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM; 516 550 517 fibril_rwlock_ read_lock( & socket_globals.lock );551 fibril_rwlock_write_lock( & socket_globals.lock ); 518 552 // find the socket 519 553 socket = sockets_find( socket_get_sockets(), socket_id ); 520 554 if( ! socket ){ 521 fibril_rwlock_ read_unlock( & socket_globals.lock );555 fibril_rwlock_write_unlock( & socket_globals.lock ); 522 556 return ENOTSOCK; 523 557 } … … 526 560 ++ socket->blocked; 527 561 while( dyn_fifo_value( & socket->accepted ) <= 0 ){ 528 fibril_rwlock_ read_unlock( & socket_globals.lock );562 fibril_rwlock_write_unlock( & socket_globals.lock ); 529 563 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 ); 531 565 } 532 566 -- 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 533 592 // 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 ); 535 594 // 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 ); 538 597 async_wait_for( message_id, ( ipcarg_t * ) & result ); 539 598 if( result > 0 ){ 599 if( result != socket_id ){ 600 result = EINVAL; 601 } 540 602 // dequeue the accepted socket if successful 541 603 dyn_fifo_pop( & socket->accepted ); 542 604 // set address length 543 605 * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer ); 606 new_socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer ); 544 607 }else if( result == ENOTSOCK ){ 545 608 // empty the queue if no accepted sockets … … 609 672 ipcarg_t result; 610 673 size_t fragments; 674 ipc_call_t answer; 611 675 612 676 if( ! data ) return EBADMEM; … … 621 685 fibril_rwlock_read_lock( & socket->sending_lock ); 622 686 // 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 } 625 693 // 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 ); 627 695 // send the address if given 628 696 if(( ! toaddr ) || ( async_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){ … … 643 711 } 644 712 } 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 } 645 719 fibril_rwlock_read_unlock( & socket->sending_lock ); 646 720 fibril_rwlock_read_unlock( & socket_globals.lock ); 647 async_wait_for( message_id, & result );648 721 return ( int ) result; 649 722 }
Note:
See TracChangeset
for help on using the changeset viewer.