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 | */ |