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; |