Rev 4713 | Rev 4722 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4713 | Rev 4720 | ||
---|---|---|---|
Line 48... | Line 48... | ||
48 | 48 | ||
49 | #include "../../structures/dynamic_fifo.h" |
49 | #include "../../structures/dynamic_fifo.h" |
50 | #include "../../structures/packet/packet_client.h" |
50 | #include "../../structures/packet/packet_client.h" |
51 | 51 | ||
52 | #include "../../include/in.h" |
52 | #include "../../include/in.h" |
- | 53 | #include "../../include/in6.h" |
|
53 | #include "../../include/inet.h" |
54 | #include "../../include/inet.h" |
54 | #include "../../include/ip_client.h" |
55 | #include "../../include/ip_client.h" |
55 | #include "../../include/ip_interface.h" |
56 | #include "../../include/ip_interface.h" |
56 | #include "../../include/ip_protocols.h" |
57 | #include "../../include/ip_protocols.h" |
57 | #include "../../include/icmp_client.h" |
58 | #include "../../include/icmp_client.h" |
Line 128... | Line 129... | ||
128 | int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ); |
129 | int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ); |
129 | 130 | ||
130 | /** Sends data from the socket to the remote address. |
131 | /** Sends data from the socket to the remote address. |
131 | * Binds the socket to a free port if not already connected/bound. |
132 | * Binds the socket to a free port if not already connected/bound. |
132 | * Handles the NET_SOCKET_SENDTO message. |
133 | * Handles the NET_SOCKET_SENDTO message. |
- | 134 | * Supports AF_INET and AF_INET6 address families. |
|
133 | * @param local_sockets The application local sockets. Input/output parameter. |
135 | * @param local_sockets The application local sockets. Input/output parameter. |
134 | * @param socket_id Socket identifier. Input parameter. |
136 | * @param socket_id Socket identifier. Input parameter. |
135 | * @param addr The destination address. Input parameter. |
137 | * @param addr The destination address. Input parameter. |
136 | * @param addrlen The address length. Input parameter. |
138 | * @param addrlen The address length. Input parameter. |
137 | * @param fragments The number of data fragments. Input parameter. |
139 | * @param fragments The number of data fragments. Input parameter. |
Line 144... | Line 146... | ||
144 | * @returns ENOMEM if there is not enough memory left. |
146 | * @returns ENOMEM if there is not enough memory left. |
145 | * @returns Other error codes as defined for the socket_read_packet_data() function. |
147 | * @returns Other error codes as defined for the socket_read_packet_data() function. |
146 | * @returns Other error codes as defined for the ip_client_prepare_packet() function. |
148 | * @returns Other error codes as defined for the ip_client_prepare_packet() function. |
147 | * @returns Other error codes as defined for the ip_send_msg() function. |
149 | * @returns Other error codes as defined for the ip_send_msg() function. |
148 | */ |
150 | */ |
149 | int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags ); |
151 | int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, int flags ); |
150 | 152 | ||
151 | /** Receives data to the socket. |
153 | /** Receives data to the socket. |
152 | * Handles the NET_SOCKET_RECVFROM message. |
154 | * Handles the NET_SOCKET_RECVFROM message. |
- | 155 | * Replies the source address as well. |
|
153 | * @param local_sockets The application local sockets. Input parameter. |
156 | * @param local_sockets The application local sockets. Input parameter. |
154 | * @param socket_id Socket identifier. Input parameter. |
157 | * @param socket_id Socket identifier. Input parameter. |
155 | * @param flags Various receive flags. Input parameter. |
158 | * @param flags Various receive flags. Input parameter. |
- | 159 | * @param addrlen The source address length. Output parameter. |
|
156 | * @returns The number of bytes received. |
160 | * @returns The number of bytes received. |
157 | * @returns ENOTSOCK if the socket is not found. |
161 | * @returns ENOTSOCK if the socket is not found. |
158 | * @returns NO_DATA if there are no received packets or data. |
162 | * @returns NO_DATA if there are no received packets or data. |
159 | * @returns ENOMEM if there is not enough memory left. |
163 | * @returns ENOMEM if there is not enough memory left. |
160 | * @returns EINVAL if the received address is not an IP address. |
164 | * @returns EINVAL if the received address is not an IP address. |
161 | * @returns Other error codes as defined for the packet_translate() function. |
165 | * @returns Other error codes as defined for the packet_translate() function. |
162 | * @returns Other error codes as defined for the socket_write_data() function. |
166 | * @returns Other error codes as defined for the socket_write_data() function. |
163 | */ |
167 | */ |
164 | int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags ); |
168 | int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ); |
165 | 169 | ||
166 | /*@}*/ |
170 | /*@}*/ |
167 | 171 | ||
168 | /** Receives data from the socket. |
172 | /** Receives data from the socket. |
169 | * The received data buffer is allocated and returned. |
173 | * The received data buffer is allocated and returned. |
Line 178... | Line 182... | ||
178 | int socket_read_data( void ** data, size_t * length ); |
182 | int socket_read_data( void ** data, size_t * length ); |
179 | 183 | ||
180 | /** Receives data from the socket into a packet. |
184 | /** Receives data from the socket into a packet. |
181 | * @param packet The new created packet. Output parameter. |
185 | * @param packet The new created packet. Output parameter. |
182 | * @param prefix Reserved packet data prefix length. Input parameter. |
186 | * @param prefix Reserved packet data prefix length. Input parameter. |
183 | * @param address_in The destination address to be set. Input parameter. |
187 | * @param addr The destination address. Input parameter. |
- | 188 | * @param addrlen The address length. Input parameter. |
|
184 | * @returns Number of bytes received. |
189 | * @returns Number of bytes received. |
185 | * @returns EINVAL if the client does not send data. |
190 | * @returns EINVAL if the client does not send data. |
186 | * @returns ENOMEM if there is not enough memory left. |
191 | * @returns ENOMEM if there is not enough memory left. |
187 | * @returns Other error codes as defined for the ipc_data_read_finalize() function. |
192 | * @returns Other error codes as defined for the ipc_data_read_finalize() function. |
188 | */ |
193 | */ |
189 | int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ); |
194 | int socket_read_packet_data( packet_ref packet, size_t prefix, const struct sockaddr * addr, socklen_t addrlen ); |
190 | 195 | ||
191 | /** Replies the data to the socket. |
196 | /** Replies the data to the socket. |
192 | * @param data The data buffer to be sent. Input parameter. |
197 | * @param data The data buffer to be sent. Input parameter. |
193 | * @param data_length The buffer length. Input parameter. |
198 | * @param data_length The buffer length. Input parameter. |
194 | * @returns EOK on success. |
199 | * @returns EOK on success. |
195 | * @returns EINVAL if the client does not expect all the data. |
200 | * @returns EINVAL if the client does not expect all the data. |
196 | * @returns Other error codes as defined for the ipc_data_read_finalize() function. |
201 | * @returns Other error codes as defined for the ipc_data_read_finalize() function. |
197 | */ |
202 | */ |
198 | int socket_write_data( void * data, size_t data_length ); |
203 | int socket_write_data( void * data, size_t data_length ); |
199 | 204 | ||
- | 205 | /** Sets the address port. |
|
- | 206 | * Supports AF_INET and AF_INET6 address families. |
|
- | 207 | * @param addr The address to be updated. Input/output parameter. |
|
- | 208 | * @param addrlen The address length. Input parameter. |
|
- | 209 | * @param port The port to be set. Input parameter. |
|
- | 210 | * @returns EOK on success. |
|
- | 211 | * @returns EINVAL if the address length does not match the address family. |
|
- | 212 | * @returns EAFNOSUPPORT if the address family is not supported. |
|
- | 213 | */ |
|
- | 214 | int udp_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port ); |
|
- | 215 | ||
200 | /** UDP global data. |
216 | /** UDP global data. |
201 | */ |
217 | */ |
202 | udp_globals_t udp_globals; |
218 | udp_globals_t udp_globals; |
203 | 219 | ||
204 | int udp_initialize( async_client_conn_t client_connection ){ |
220 | int udp_initialize( async_client_conn_t client_connection ){ |
Line 350... | Line 366... | ||
350 | int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){ |
366 | int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){ |
351 | int res; |
367 | int res; |
352 | bool keep_on_going = true; |
368 | bool keep_on_going = true; |
353 | socket_cores_t local_sockets; |
369 | socket_cores_t local_sockets; |
354 | int app_phone = IPC_GET_PHONE( & call ); |
370 | int app_phone = IPC_GET_PHONE( & call ); |
355 | void * addr; |
371 | struct sockaddr * addr; |
356 | size_t addrlen; |
372 | size_t addrlen; |
357 | fibril_rwlock_t lock; |
373 | fibril_rwlock_t lock; |
358 | ipc_call_t answer; |
374 | ipc_call_t answer; |
359 | int answer_count; |
375 | int answer_count; |
360 | 376 | ||
Line 386... | Line 402... | ||
386 | * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t ); |
402 | * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t ); |
387 | * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE; |
403 | * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE; |
388 | answer_count = 3; |
404 | answer_count = 3; |
389 | break; |
405 | break; |
390 | case NET_SOCKET_BIND: |
406 | case NET_SOCKET_BIND: |
391 | res = socket_read_data( & addr, & addrlen ); |
407 | res = socket_read_data(( void ** ) & addr, & addrlen ); |
392 | if( res == EOK ){ |
408 | if( res == EOK ){ |
393 | fibril_rwlock_write_lock( & lock ); |
409 | fibril_rwlock_write_lock( & lock ); |
394 | fibril_rwlock_write_lock( & udp_globals.lock ); |
410 | fibril_rwlock_write_lock( & udp_globals.lock ); |
395 | 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 ); |
411 | 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 ); |
396 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
412 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
397 | fibril_rwlock_write_unlock( & lock ); |
413 | fibril_rwlock_write_unlock( & lock ); |
398 | free( addr ); |
414 | free( addr ); |
399 | } |
415 | } |
400 | break; |
416 | break; |
401 | case NET_SOCKET_SENDTO: |
417 | case NET_SOCKET_SENDTO: |
402 | res = socket_read_data( & addr, & addrlen ); |
418 | res = socket_read_data(( void ** ) & addr, & addrlen ); |
403 | if( res == EOK ){ |
419 | if( res == EOK ){ |
404 | fibril_rwlock_read_lock( & lock ); |
420 | fibril_rwlock_read_lock( & lock ); |
405 | fibril_rwlock_read_lock( & udp_globals.lock ); |
421 | fibril_rwlock_read_lock( & udp_globals.lock ); |
406 | res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call )); |
422 | res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call )); |
407 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
423 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
Line 410... | Line 426... | ||
410 | } |
426 | } |
411 | break; |
427 | break; |
412 | case NET_SOCKET_RECVFROM: |
428 | case NET_SOCKET_RECVFROM: |
413 | fibril_rwlock_read_lock( & lock ); |
429 | fibril_rwlock_read_lock( & lock ); |
414 | fibril_rwlock_read_lock( & udp_globals.lock ); |
430 | fibril_rwlock_read_lock( & udp_globals.lock ); |
415 | res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call )); |
431 | res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen ); |
416 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
432 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
417 | fibril_rwlock_read_unlock( & lock ); |
433 | fibril_rwlock_read_unlock( & lock ); |
418 | if( res > 0 ){ |
434 | if( res > 0 ){ |
419 | * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
435 | * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
420 | * SOCKET_SET_ADDRESS_LENGTH( answer ) = sizeof( struct sockaddr_in ); |
436 | * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; |
421 | answer_count = 2; |
437 | answer_count = 2; |
422 | res = EOK; |
438 | res = EOK; |
423 | } |
439 | } |
424 | break; |
440 | break; |
425 | case NET_SOCKET_CLOSE: |
441 | case NET_SOCKET_CLOSE: |
Line 444... | Line 460... | ||
444 | socket_cores_destroy( & local_sockets ); |
460 | socket_cores_destroy( & local_sockets ); |
445 | 461 | ||
446 | return EOK; |
462 | return EOK; |
447 | } |
463 | } |
448 | 464 | ||
449 | int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags ){ |
465 | int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, int flags ){ |
450 | ERROR_DECLARE; |
466 | ERROR_DECLARE; |
451 | 467 | ||
452 | socket_core_ref socket; |
468 | socket_core_ref socket; |
453 | struct sockaddr * address; |
- | |
454 | struct sockaddr_in * address_in; |
469 | struct sockaddr_in * address_in; |
- | 470 | struct sockaddr_in6 * address_in6; |
|
455 | packet_t packet; |
471 | packet_t packet; |
456 | packet_t next_packet; |
472 | packet_t next_packet; |
457 | udp_header_ref header; |
473 | udp_header_ref header; |
458 | int index; |
474 | int index; |
459 | size_t total_length; |
475 | size_t total_length; |
460 | int result; |
476 | int result; |
- | 477 | uint16_t dest_port; |
|
461 | 478 | ||
462 | if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
479 | if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
463 | address = ( struct sockaddr * ) addr; |
- | |
464 | switch( address->sa_family ){ |
480 | switch( addr->sa_family ){ |
465 | case AF_INET: |
481 | case AF_INET: |
466 | if( addrlen != sizeof( struct sockaddr_in )) return EINVAL; |
482 | if( addrlen != sizeof( struct sockaddr_in )) return EINVAL; |
467 | address_in = ( struct sockaddr_in * ) addr; |
483 | address_in = ( struct sockaddr_in * ) addr; |
- | 484 | dest_port = address_in->sin_port; |
|
- | 485 | break; |
|
- | 486 | case AF_INET6: |
|
468 | socket = socket_cores_find( local_sockets, socket_id ); |
487 | if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
- | 488 | address_in6 = ( struct sockaddr_in6 * ) addr; |
|
- | 489 | dest_port = address_in6->sin6_port; |
|
- | 490 | break; |
|
- | 491 | default: |
|
469 | if( ! socket ) return ENOTSOCK; |
492 | return EAFNOSUPPORT; |
- | 493 | } |
|
470 | 494 | ||
471 | // bind the socket to a random free port if not bound |
- | |
472 | while( socket->port <= 0 ){ |
- | |
473 | // try to find a free port |
- | |
474 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
- | |
475 | fibril_rwlock_write_lock( & udp_globals.lock ); |
495 | socket = socket_cores_find( local_sockets, socket_id ); |
476 | if( socket->port <= 0 ){ |
496 | if( ! socket ) return ENOTSOCK; |
477 | ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port )); |
- | |
478 | // set the next port as the search starting port number |
- | |
479 | udp_globals.last_used_port = socket->port; |
- | |
480 | } |
- | |
481 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
- | |
482 | fibril_rwlock_read_lock( & udp_globals.lock ); |
- | |
483 | } |
- | |
484 | // TODO do not ask all the time |
- | |
485 | ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix )); |
- | |
486 | 497 | ||
487 | // read the first packet fragment |
498 | // bind the socket to a random free port if not bound |
488 | result = socket_read_packet_data( & packet, sizeof( udp_header_t ), address_in ); |
- | |
489 | if( result < 0 ) return result; |
499 | while( socket->port <= 0 ){ |
490 | total_length = ( size_t ) result; |
500 | // try to find a free port |
491 | // prefix the udp header |
501 | fibril_rwlock_read_unlock( & udp_globals.lock ); |
492 | header = PACKET_PREFIX( packet, udp_header_t ); |
502 | fibril_rwlock_write_lock( & udp_globals.lock ); |
493 | if( ! header ){ |
503 | if( socket->port <= 0 ){ |
494 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
504 | ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port )); |
495 | return ENOMEM; |
- | |
496 | } |
- | |
497 | // read the rest of the packet fragments |
505 | // set the next port as the search starting port number |
498 | for( index = 1; index < fragments; ++ index ){ |
- | |
499 | result = socket_read_packet_data( & next_packet, 0, address_in ); |
- | |
500 | if( result < 0 ){ |
- | |
501 | return udp_release_and_return( packet, result ); |
506 | udp_globals.last_used_port = socket->port; |
502 | } |
507 | } |
503 | packet = pq_add( packet, next_packet, index, 0 ); |
508 | fibril_rwlock_write_unlock( & udp_globals.lock ); |
504 | total_length += ( size_t ) result; |
509 | fibril_rwlock_read_lock( & udp_globals.lock ); |
505 | } |
510 | } |
- | 511 | ||
506 | // set the udp header |
512 | // TODO do not ask all the time |
507 | header->source = htons( socket->port ); |
513 | ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix )); |
- | 514 | ||
508 | header->dest = htons( address_in->sin_port ); |
515 | // read the first packet fragment |
509 | header->len = htons( total_length + sizeof( udp_header_t )); |
516 | result = socket_read_packet_data( & packet, sizeof( udp_header_t ), addr, addrlen ); |
510 | // TODO my ip address for the pseudo header checksum |
517 | if( result < 0 ) return result; |
511 | header->check = 0; |
518 | total_length = ( size_t ) result; |
512 | // prepare the first packet fragment |
519 | // prefix the udp header |
513 | if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){ |
- | |
514 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
520 | header = PACKET_PREFIX( packet, udp_header_t ); |
515 | return ERROR_CODE; |
- | |
516 | } |
- | |
517 | // send the packet |
521 | if( ! header ){ |
518 | return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP, 0 ); |
522 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
519 | // TODO IPv6 |
523 | return ENOMEM; |
520 | } |
524 | } |
- | 525 | // read the rest of the packet fragments |
|
- | 526 | for( index = 1; index < fragments; ++ index ){ |
|
- | 527 | result = socket_read_packet_data( & next_packet, 0, addr, addrlen ); |
|
- | 528 | if( result < 0 ){ |
|
- | 529 | return udp_release_and_return( packet, result ); |
|
- | 530 | } |
|
- | 531 | packet = pq_add( packet, next_packet, index, 0 ); |
|
- | 532 | total_length += ( size_t ) result; |
|
- | 533 | } |
|
- | 534 | // set the udp header |
|
- | 535 | header->source = htons( socket->port ); |
|
- | 536 | header->dest = htons( dest_port ); |
|
- | 537 | header->len = htons( total_length + sizeof( udp_header_t )); |
|
- | 538 | // TODO my ip address for the pseudo header checksum |
|
- | 539 | header->check = 0; |
|
- | 540 | // prepare the first packet fragment |
|
- | 541 | if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){ |
|
- | 542 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
|
521 | return EAFNOSUPPORT; |
543 | return ERROR_CODE; |
- | 544 | } |
|
- | 545 | // send the packet |
|
- | 546 | return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP, 0 ); |
|
522 | } |
547 | } |
523 | 548 | ||
524 | int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags ){ |
549 | int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){ |
525 | ERROR_DECLARE; |
550 | ERROR_DECLARE; |
526 | 551 | ||
527 | socket_core_ref socket; |
552 | socket_core_ref socket; |
528 | int packet_id; |
553 | int packet_id; |
529 | packet_t packet; |
554 | packet_t packet; |
530 | udp_header_ref header; |
555 | udp_header_ref header; |
531 | struct sockaddr_in address; |
556 | struct sockaddr * addr; |
532 | size_t length; |
557 | size_t length; |
533 | packet_t next_packet; |
558 | packet_t next_packet; |
534 | uint8_t * data; |
559 | uint8_t * data; |
535 | size_t fragments; |
560 | size_t fragments; |
536 | size_t * lengths; |
561 | size_t * lengths; |
537 | int result; |
- | |
538 | size_t index; |
562 | size_t index; |
539 | uint8_t * addr; |
563 | int result; |
540 | 564 | ||
541 | // find the socket |
565 | // find the socket |
542 | socket = socket_cores_find( local_sockets, socket_id ); |
566 | socket = socket_cores_find( local_sockets, socket_id ); |
543 | if( ! socket ) return ENOTSOCK; |
567 | if( ! socket ) return ENOTSOCK; |
544 | // get the next received packet |
568 | // get the next received packet |
Line 550... | Line 574... | ||
550 | if( ! data ){ |
574 | if( ! data ){ |
551 | pq_release( udp_globals.net_phone, packet_id ); |
575 | pq_release( udp_globals.net_phone, packet_id ); |
552 | return NO_DATA; |
576 | return NO_DATA; |
553 | } |
577 | } |
554 | header = ( udp_header_ref ) data; |
578 | header = ( udp_header_ref ) data; |
- | 579 | ||
555 | // set the source address |
580 | // set the source address port |
556 | address.sin_family = PF_INET; |
- | |
557 | address.sin_port = ntohs( header->source ); |
- | |
558 | result = packet_get_addr( packet, & addr, NULL ); |
581 | result = packet_get_addr( packet, ( uint8_t ** ) & addr, NULL ); |
559 | if( result != sizeof( address.sin_addr.s_addr )){ |
582 | if( ERROR_OCCURRED( udp_set_address_port( addr, result, ntohs( header->source )))){ |
560 | pq_release( udp_globals.net_phone, packet_id ); |
583 | pq_release( udp_globals.net_phone, packet_id ); |
561 | return EINVAL; |
584 | return ERROR_CODE; |
562 | } |
585 | } |
563 | address.sin_addr.s_addr = *(( uint32_t * ) addr ); |
586 | * addrlen = ( size_t ) result; |
564 | bzero( & address.sin_zero, sizeof( address.sin_zero )); |
- | |
565 | // send the source address |
587 | // send the source address |
566 | ERROR_PROPAGATE( socket_write_data( & address, sizeof( address ))); |
588 | ERROR_PROPAGATE( socket_write_data( addr, * addrlen )); |
- | 589 | ||
567 | next_packet = pq_next( packet ); |
590 | next_packet = pq_next( packet ); |
568 | if( ! next_packet ){ |
591 | if( ! next_packet ){ |
569 | // write all if only one fragment |
592 | // write all if only one fragment |
570 | ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t ))); |
593 | ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t ))); |
571 | // store the total length |
594 | // store the total length |
Line 634... | Line 657... | ||
634 | return ERROR_CODE; |
657 | return ERROR_CODE; |
635 | } |
658 | } |
636 | return EOK; |
659 | return EOK; |
637 | } |
660 | } |
638 | 661 | ||
639 | int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ){ |
662 | int socket_read_packet_data( packet_ref packet, size_t prefix, const struct sockaddr * addr, socklen_t addrlen ){ |
640 | ERROR_DECLARE; |
663 | ERROR_DECLARE; |
641 | 664 | ||
642 | ipc_callid_t callid; |
665 | ipc_callid_t callid; |
643 | size_t length; |
666 | size_t length; |
644 | void * data; |
667 | void * data; |
Line 655... | Line 678... | ||
655 | return ENOMEM; |
678 | return ENOMEM; |
656 | } |
679 | } |
657 | // read the data into the packet |
680 | // read the data into the packet |
658 | if( ERROR_OCCURRED( ipc_data_write_finalize( callid, data, length )) |
681 | if( ERROR_OCCURRED( ipc_data_write_finalize( callid, data, length )) |
659 | // set the packet destination address |
682 | // set the packet destination address |
660 | || ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) & address_in->sin_addr.s_addr, sizeof( address_in->sin_addr.s_addr )))){ |
683 | || ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) addr, addrlen ))){ |
661 | pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
684 | pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
662 | return ERROR_CODE; |
685 | return ERROR_CODE; |
663 | } |
686 | } |
664 | return ( int ) length; |
687 | return ( int ) length; |
665 | } |
688 | } |
Line 689... | Line 712... | ||
689 | }else{ |
712 | }else{ |
690 | udp_release_and_return( packet, EINVAL ); |
713 | udp_release_and_return( packet, EINVAL ); |
691 | } |
714 | } |
692 | } |
715 | } |
693 | 716 | ||
- | 717 | int udp_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port ){ |
|
- | 718 | struct sockaddr_in * address_in; |
|
- | 719 | struct sockaddr_in6 * address_in6; |
|
- | 720 | size_t length; |
|
- | 721 | ||
- | 722 | if( addrlen < 0 ) return EINVAL; |
|
- | 723 | length = ( size_t ) addrlen; |
|
- | 724 | if( length < sizeof( struct sockaddr )) return EINVAL; |
|
- | 725 | switch( addr->sa_family ){ |
|
- | 726 | case AF_INET: |
|
- | 727 | if( length != sizeof( struct sockaddr_in )) return EINVAL; |
|
- | 728 | address_in = ( struct sockaddr_in * ) addr; |
|
- | 729 | address_in->sin_port = port; |
|
- | 730 | return EOK; |
|
- | 731 | case AF_INET6: |
|
- | 732 | if( length != sizeof( struct sockaddr_in6 )) return EINVAL; |
|
- | 733 | address_in6 = ( struct sockaddr_in6 * ) addr; |
|
- | 734 | address_in6->sin6_port = port; |
|
- | 735 | return EOK; |
|
- | 736 | default: |
|
- | 737 | return EAFNOSUPPORT; |
|
- | 738 | } |
|
- | 739 | } |
|
- | 740 | ||
694 | /** @} |
741 | /** @} |
695 | */ |
742 | */ |