Rev 4731 | Rev 4743 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4731 | Rev 4738 | ||
|---|---|---|---|
| Line 228... | Line 228... | ||
| 228 | } |
228 | } |
| 229 | 229 | ||
| 230 | int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){ |
230 | int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){ |
| 231 | int result; |
231 | int result; |
| 232 | 232 | ||
| 233 | fibril_rwlock_read_lock( & udp_globals.lock ); |
233 | fibril_rwlock_write_lock( & udp_globals.lock ); |
| 234 | result = udp_process_packet( packet, error ); |
234 | result = udp_process_packet( packet, error ); |
| 235 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
235 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
| 236 | 236 | ||
| 237 | return result; |
237 | return result; |
| 238 | } |
238 | } |
| 239 | 239 | ||
| 240 | int udp_process_packet( packet_t packet, services_t error ){ |
240 | int udp_process_packet( packet_t packet, services_t error ){ |
| Line 242... | Line 242... | ||
| 242 | 242 | ||
| 243 | size_t length; |
243 | size_t length; |
| 244 | size_t offset; |
244 | size_t offset; |
| 245 | int result; |
245 | int result; |
| 246 | udp_header_ref header; |
246 | udp_header_ref header; |
| 247 | socket_core_ref * socket; |
247 | socket_core_ref socket; |
| 248 | packet_t next_packet; |
248 | packet_t next_packet; |
| 249 | size_t total_length; |
249 | size_t total_length; |
| 250 | uint32_t checksum; |
250 | uint32_t checksum; |
| 251 | int fragments; |
251 | int fragments; |
| 252 | packet_t tmp_packet; |
252 | packet_t tmp_packet; |
| Line 299... | Line 299... | ||
| 299 | header = ( udp_header_ref ) packet_get_data( packet ); |
299 | header = ( udp_header_ref ) packet_get_data( packet ); |
| 300 | if( ! header ){ |
300 | if( ! header ){ |
| 301 | return udp_release_and_return( packet, NO_DATA ); |
301 | return udp_release_and_return( packet, NO_DATA ); |
| 302 | } |
302 | } |
| 303 | // find the destination socket |
303 | // find the destination socket |
| 304 | socket = socket_ports_find( & udp_globals.sockets, ntohs( header->destination_port )); |
304 | socket = socket_port_find( & udp_globals.sockets, ntohs( header->destination_port ), SOCKET_MAP_KEY_LISTENING, 0 ); |
| 305 | if( ! socket ){ |
305 | if( ! socket ){ |
| 306 | if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){ |
306 | if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){ |
| 307 | icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet ); |
307 | icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet ); |
| 308 | } |
308 | } |
| 309 | return EADDRNOTAVAIL; |
309 | return EADDRNOTAVAIL; |
| Line 372... | Line 372... | ||
| 372 | return EINVAL; |
372 | return EINVAL; |
| 373 | } |
373 | } |
| 374 | } |
374 | } |
| 375 | 375 | ||
| 376 | // queue the received packet |
376 | // queue the received packet |
| 377 | if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){ |
377 | if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){ |
| 378 | return udp_release_and_return( packet, ERROR_CODE ); |
378 | return udp_release_and_return( packet, ERROR_CODE ); |
| 379 | } |
379 | } |
| 380 | 380 | ||
| 381 | // notify the destination socket |
381 | // notify the destination socket |
| 382 | async_msg_5(( ** socket ).phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) ( ** socket ).socket_id, 0, 0, 0, ( ipcarg_t ) fragments ); |
382 | async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments ); |
| 383 | return EOK; |
383 | return EOK; |
| 384 | } |
384 | } |
| 385 | 385 | ||
| 386 | int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
386 | int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
| 387 | ERROR_DECLARE; |
387 | ERROR_DECLARE; |
| Line 406... | Line 406... | ||
| 406 | bool keep_on_going = true; |
406 | bool keep_on_going = true; |
| 407 | socket_cores_t local_sockets; |
407 | socket_cores_t local_sockets; |
| 408 | int app_phone = IPC_GET_PHONE( & call ); |
408 | int app_phone = IPC_GET_PHONE( & call ); |
| 409 | struct sockaddr * addr; |
409 | struct sockaddr * addr; |
| 410 | size_t addrlen; |
410 | size_t addrlen; |
| 411 | // fibril_rwlock_t lock; |
411 | fibril_rwlock_t lock; |
| 412 | ipc_call_t answer; |
412 | ipc_call_t answer; |
| 413 | int answer_count; |
413 | int answer_count; |
| 414 | 414 | ||
| 415 | /* |
415 | /* |
| 416 | * Accept the connection |
416 | * Accept the connection |
| Line 419... | Line 419... | ||
| 419 | ipc_answer_0( callid, EOK ); |
419 | ipc_answer_0( callid, EOK ); |
| 420 | 420 | ||
| 421 | // The client connection is only in one fibril and therefore no additional locks are needed. |
421 | // The client connection is only in one fibril and therefore no additional locks are needed. |
| 422 | 422 | ||
| 423 | socket_cores_initialize( & local_sockets ); |
423 | socket_cores_initialize( & local_sockets ); |
| 424 | // fibril_rwlock_initialize( & lock ); |
424 | fibril_rwlock_initialize( & lock ); |
| 425 | 425 | ||
| 426 | while( keep_on_going ){ |
426 | while( keep_on_going ){ |
| 427 | // refresh data |
427 | // refresh data |
| 428 | refresh_answer( & answer, & answer_count ); |
428 | refresh_answer( & answer, & answer_count ); |
| 429 | 429 | ||
| Line 434... | Line 434... | ||
| 434 | case IPC_M_PHONE_HUNGUP: |
434 | case IPC_M_PHONE_HUNGUP: |
| 435 | keep_on_going = false; |
435 | keep_on_going = false; |
| 436 | res = EOK; |
436 | res = EOK; |
| 437 | break; |
437 | break; |
| 438 | case NET_SOCKET: |
438 | case NET_SOCKET: |
| 439 | // fibril_rwlock_write_lock( & lock ); |
439 | fibril_rwlock_write_lock( & lock ); |
| 440 | res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer )); |
440 | res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer )); |
| 441 | // fibril_rwlock_write_unlock( & lock ); |
441 | fibril_rwlock_write_unlock( & lock ); |
| 442 | // TODO max fragment size |
442 | // TODO max fragment size |
| 443 | * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE; |
443 | * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE; |
| 444 | * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t ); |
444 | * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t ); |
| 445 | answer_count = 3; |
445 | answer_count = 3; |
| 446 | break; |
446 | break; |
| 447 | case NET_SOCKET_BIND: |
447 | case NET_SOCKET_BIND: |
| 448 | res = data_receive(( void ** ) & addr, & addrlen ); |
448 | res = data_receive(( void ** ) & addr, & addrlen ); |
| 449 | if( res == EOK ){ |
449 | if( res == EOK ){ |
| 450 | // fibril_rwlock_write_lock( & lock ); |
450 | fibril_rwlock_read_lock( & lock ); |
| 451 | fibril_rwlock_write_lock( & udp_globals.lock ); |
451 | fibril_rwlock_write_lock( & udp_globals.lock ); |
| 452 | 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 ); |
452 | 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 ); |
| 453 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
453 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
| 454 | // fibril_rwlock_write_unlock( & lock ); |
454 | fibril_rwlock_read_unlock( & lock ); |
| 455 | free( addr ); |
455 | free( addr ); |
| 456 | } |
456 | } |
| 457 | break; |
457 | break; |
| 458 | case NET_SOCKET_SENDTO: |
458 | case NET_SOCKET_SENDTO: |
| 459 | res = data_receive(( void ** ) & addr, & addrlen ); |
459 | res = data_receive(( void ** ) & addr, & addrlen ); |
| 460 | if( res == EOK ){ |
460 | if( res == EOK ){ |
| 461 | // fibril_rwlock_read_lock( & lock ); |
461 | fibril_rwlock_read_lock( & lock ); |
| 462 | fibril_rwlock_read_lock( & udp_globals.lock ); |
462 | fibril_rwlock_write_lock( & udp_globals.lock ); |
| 463 | res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call )); |
463 | res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call )); |
| 464 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
464 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
| 465 | // fibril_rwlock_read_unlock( & lock ); |
465 | fibril_rwlock_read_unlock( & lock ); |
| 466 | free( addr ); |
466 | free( addr ); |
| 467 | } |
467 | } |
| 468 | break; |
468 | break; |
| 469 | case NET_SOCKET_RECVFROM: |
469 | case NET_SOCKET_RECVFROM: |
| 470 | // fibril_rwlock_read_lock( & lock ); |
470 | fibril_rwlock_read_lock( & lock ); |
| 471 | fibril_rwlock_read_lock( & udp_globals.lock ); |
471 | fibril_rwlock_write_lock( & udp_globals.lock ); |
| 472 | res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen ); |
472 | res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen ); |
| 473 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
473 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
| 474 | // fibril_rwlock_read_unlock( & lock ); |
474 | fibril_rwlock_read_unlock( & lock ); |
| 475 | if( res > 0 ){ |
475 | if( res > 0 ){ |
| 476 | * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
476 | * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
| 477 | * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; |
477 | * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; |
| 478 | answer_count = 2; |
478 | answer_count = 2; |
| 479 | res = EOK; |
479 | res = EOK; |
| 480 | } |
480 | } |
| 481 | break; |
481 | break; |
| 482 | case NET_SOCKET_CLOSE: |
482 | case NET_SOCKET_CLOSE: |
| 483 | // fibril_rwlock_write_lock( & lock ); |
483 | fibril_rwlock_write_lock( & lock ); |
| 484 | fibril_rwlock_write_lock( & udp_globals.lock ); |
484 | fibril_rwlock_write_lock( & udp_globals.lock ); |
| 485 | res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets ); |
485 | res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets, NULL ); |
| 486 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
486 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
| 487 | // fibril_rwlock_write_unlock( & lock ); |
487 | fibril_rwlock_write_unlock( & lock ); |
| 488 | break; |
488 | break; |
| 489 | case NET_SOCKET_GETSOCKOPT: |
489 | case NET_SOCKET_GETSOCKOPT: |
| 490 | case NET_SOCKET_SETSOCKOPT: |
490 | case NET_SOCKET_SETSOCKOPT: |
| 491 | default: |
491 | default: |
| 492 | res = ENOTSUP; |
492 | res = ENOTSUP; |
| Line 496... | Line 496... | ||
| 496 | // printf( "res = %d\n", res ); |
496 | // printf( "res = %d\n", res ); |
| 497 | 497 | ||
| 498 | answer_call( callid, res, & answer, answer_count ); |
498 | answer_call( callid, res, & answer, answer_count ); |
| 499 | } |
499 | } |
| 500 | 500 | ||
| 501 | // TODO call socket_destroy() on all bound! |
501 | // release all local sockets |
| 502 | socket_cores_destroy( & local_sockets ); |
502 | socket_cores_release( udp_globals.net_phone, & local_sockets, & udp_globals.sockets, NULL ); |
| 503 | 503 | ||
| 504 | return EOK; |
504 | return EOK; |
| 505 | } |
505 | } |
| 506 | 506 | ||
| 507 | 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 ){ |
507 | 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 ){ |
| Line 527... | Line 527... | ||
| 527 | 527 | ||
| 528 | if(( socket->port <= 0 ) && udp_globals.autobinding ){ |
528 | if(( socket->port <= 0 ) && udp_globals.autobinding ){ |
| 529 | // bind the socket to a random free port if not bound |
529 | // bind the socket to a random free port if not bound |
| 530 | do{ |
530 | do{ |
| 531 | // try to find a free port |
531 | // try to find a free port |
| 532 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
532 | // fibril_rwlock_read_unlock( & udp_globals.lock ); |
| 533 | fibril_rwlock_write_lock( & udp_globals.lock ); |
533 | // fibril_rwlock_write_lock( & udp_globals.lock ); |
| 534 | // might be changed in the meantime |
534 | // might be changed in the meantime |
| 535 | if( socket->port <= 0 ){ |
535 | if( socket->port <= 0 ){ |
| 536 | ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port )); |
536 | if( ERROR_OCCURRED( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ))){ |
| - | 537 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
|
| - | 538 | fibril_rwlock_read_lock( & udp_globals.lock ); |
|
| - | 539 | return ERROR_CODE; |
|
| - | 540 | } |
|
| 537 | // set the next port as the search starting port number |
541 | // set the next port as the search starting port number |
| 538 | udp_globals.last_used_port = socket->port; |
542 | udp_globals.last_used_port = socket->port; |
| 539 | } |
543 | } |
| 540 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
544 | // fibril_rwlock_write_unlock( & udp_globals.lock ); |
| 541 | fibril_rwlock_read_lock( & udp_globals.lock ); |
545 | // fibril_rwlock_read_lock( & udp_globals.lock ); |
| 542 | // might be changed in the meantime |
546 | // might be changed in the meantime |
| 543 | }while( socket->port <= 0 ); |
547 | }while( socket->port <= 0 ); |
| 544 | } |
548 | } |
| 545 | 549 | ||
| 546 | // TODO do not ask all the time |
550 | // TODO do not ask all the time |
| Line 608... | Line 612... | ||
| 608 | int packet_id; |
612 | int packet_id; |
| 609 | packet_t packet; |
613 | packet_t packet; |
| 610 | udp_header_ref header; |
614 | udp_header_ref header; |
| 611 | struct sockaddr * addr; |
615 | struct sockaddr * addr; |
| 612 | size_t length; |
616 | size_t length; |
| 613 | packet_t next_packet; |
- | |
| 614 | uint8_t * data; |
617 | uint8_t * data; |
| 615 | size_t fragments; |
- | |
| 616 | size_t * lengths; |
- | |
| 617 | size_t index; |
- | |
| 618 | int result; |
618 | int result; |
| 619 | 619 | ||
| 620 | // find the socket |
620 | // find the socket |
| 621 | socket = socket_cores_find( local_sockets, socket_id ); |
621 | socket = socket_cores_find( local_sockets, socket_id ); |
| 622 | if( ! socket ) return ENOTSOCK; |
622 | if( ! socket ) return ENOTSOCK; |
| Line 640... | Line 640... | ||
| 640 | } |
640 | } |
| 641 | * addrlen = ( size_t ) result; |
641 | * addrlen = ( size_t ) result; |
| 642 | // send the source address |
642 | // send the source address |
| 643 | ERROR_PROPAGATE( data_reply( addr, * addrlen )); |
643 | ERROR_PROPAGATE( data_reply( addr, * addrlen )); |
| 644 | 644 | ||
| 645 | next_packet = pq_next( packet ); |
- | |
| 646 | if( ! next_packet ){ |
- | |
| 647 | // write all if only one fragment |
- | |
| 648 | ERROR_PROPAGATE( data_reply( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t ))); |
- | |
| 649 | // store the total length |
645 | // trim the header |
| 650 | length = packet_get_data_length( packet ) - sizeof( udp_header_t ); |
646 | ERROR_PROPAGATE( packet_trim( packet, sizeof( udp_header_t ), 0 )); |
| 651 | }else{ |
- | |
| 652 | // count the packet fragments |
- | |
| 653 | fragments = 1; |
- | |
| 654 | next_packet = pq_next( packet ); |
- | |
| 655 | while(( next_packet = pq_next( next_packet ))){ |
- | |
| 656 | ++ fragments; |
- | |
| 657 | } |
647 | |
| 658 | // compute and store the fragment lengths |
- | |
| 659 | lengths = ( size_t * ) malloc( sizeof( size_t ) * fragments + sizeof( size_t )); |
- | |
| 660 | if( ! lengths ) return ENOMEM; |
- | |
| 661 | lengths[ 0 ] = packet_get_data_length( packet ) - sizeof( udp_header_t ); |
- | |
| 662 | lengths[ fragments ] = lengths[ 0 ]; |
- | |
| 663 | next_packet = pq_next( packet ); |
- | |
| 664 | for( index = 1; index < fragments; ++ index ){ |
- | |
| 665 | lengths[ index ] = packet_get_data_length( next_packet ); |
- | |
| 666 | lengths[ fragments ] += lengths[ index ]; |
- | |
| 667 | next_packet = pq_next( packet ); |
- | |
| 668 | }while( next_packet ); |
- | |
| 669 | // write the fragment lengths |
648 | // reply the packets |
| 670 | ERROR_PROPAGATE( data_reply( lengths, sizeof( int ) * ( fragments + 1 ))); |
- | |
| 671 | // write the first fragment |
- | |
| 672 | ERROR_PROPAGATE( data_reply( data + sizeof( udp_header_t ), lengths[ 0 ] )); |
- | |
| 673 | next_packet = pq_next( packet ); |
- | |
| 674 | // write the rest of the fragments |
- | |
| 675 | for( index = 1; index < fragments; ++ index ){ |
- | |
| 676 | ERROR_PROPAGATE( data_reply( packet_get_data( next_packet ), lengths[ index ] )); |
649 | ERROR_PROPAGATE( socket_reply_packets( packet, & length )); |
| 677 | next_packet = pq_next( packet ); |
- | |
| 678 | }while( next_packet ); |
- | |
| 679 | // store the total length |
- | |
| 680 | length = lengths[ fragments ]; |
- | |
| 681 | free( lengths ); |
- | |
| 682 | } |
650 | |
| 683 | // release the packet |
651 | // release the packet |
| 684 | dyn_fifo_pop( & socket->received ); |
652 | dyn_fifo_pop( & socket->received ); |
| 685 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
653 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
| 686 | // return the total length |
654 | // return the total length |
| 687 | return ( int ) length; |
655 | return ( int ) length; |