Changeset 0b749a3 in mainline for uspace/srv/net/tl/udp/udp.c


Ignore:
Timestamp:
2010-11-22T15:39:53Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0eddb76, aae339e9
Parents:
9a1d8ab (diff), 8cd1aa5e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/udp/udp.c

    r9a1d8ab r0b749a3  
    2828
    2929/** @addtogroup udp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  UDP module implementation.
    35  *  @see udp.h
    36  */
     34 * UDP module implementation.
     35 * @see udp.h
     36 */
     37
     38#include "udp.h"
     39#include "udp_header.h"
     40#include "udp_module.h"
    3741
    3842#include <async.h>
     
    4246#include <ipc/ipc.h>
    4347#include <ipc/services.h>
    44 
    45 #include <net_err.h>
    46 #include <net_messages.h>
    47 #include <net_modules.h>
     48#include <ipc/net.h>
     49#include <ipc/tl.h>
     50#include <ipc/socket.h>
    4851#include <adt/dynamic_fifo.h>
    49 #include <packet/packet_client.h>
     52#include <errno.h>
     53
     54#include <net/socket_codes.h>
     55#include <net/ip_protocols.h>
     56#include <net/in.h>
     57#include <net/in6.h>
     58#include <net/inet.h>
     59#include <net/modules.h>
     60
     61#include <packet_client.h>
    5062#include <packet_remote.h>
    5163#include <net_checksum.h>
    52 #include <in.h>
    53 #include <in6.h>
    54 #include <inet.h>
    5564#include <ip_client.h>
    5665#include <ip_interface.h>
    57 #include <ip_protocols.h>
    5866#include <icmp_client.h>
    5967#include <icmp_interface.h>
    6068#include <net_interface.h>
    61 #include <socket_codes.h>
    62 #include <socket_errno.h>
    6369#include <socket_core.h>
    64 #include <socket_messages.h>
    6570#include <tl_common.h>
    6671#include <tl_local.h>
    6772#include <tl_interface.h>
    68 #include <tl_messages.h>
    69 
    70 #include "udp.h"
    71 #include "udp_header.h"
    72 #include "udp_module.h"
    73 
    74 /** UDP module name.
    75  */
     73
     74/** UDP module name. */
    7675#define NAME    "UDP protocol"
    7776
    78 /** Default UDP checksum computing.
    79  */
     77/** Default UDP checksum computing. */
    8078#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING      true
    8179
    82 /** Default UDP autobind when sending via unbound sockets.
    83  */
     80/** Default UDP autobind when sending via unbound sockets. */
    8481#define NET_DEFAULT_UDP_AUTOBINDING     true
    8582
    86 /** Maximum UDP fragment size.
    87  */
    88 #define MAX_UDP_FRAGMENT_SIZE   65535
    89 
    90 /** Free ports pool start.
    91  */
    92 #define UDP_FREE_PORTS_START    1025
    93 
    94 /** Free ports pool end.
    95  */
     83/** Maximum UDP fragment size. */
     84#define MAX_UDP_FRAGMENT_SIZE           65535
     85
     86/** Free ports pool start. */
     87#define UDP_FREE_PORTS_START            1025
     88
     89/** Free ports pool end. */
    9690#define UDP_FREE_PORTS_END              65535
    9791
    98 /** Processes the received UDP packet queue.
    99  *  Is used as an entry point from the underlying IP module.
    100  *  Locks the global lock and calls udp_process_packet() function.
    101  *  @param[in] device_id The receiving device identifier.
    102  *  @param[in,out] packet The received packet queue.
    103  *  @param receiver The target service. Ignored parameter.
    104  *  @param[in] error The packet error reporting service. Prefixes the received packet.
    105  *  @returns EOK on success.
    106  *  @returns Other error codes as defined for the udp_process_packet() function.
    107  */
    108 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
    109 
    110 /** Processes the received UDP packet queue.
    111  *  Notifies the destination socket application.
    112  *  Releases the packet on error or sends an ICMP error notification..
    113  *  @param[in] device_id The receiving device identifier.
    114  *  @param[in,out] packet The received packet queue.
    115  *  @param[in] error The packet error reporting service. Prefixes the received packet.
    116  *  @returns EOK on success.
    117  *  @returns EINVAL if the packet is not valid.
    118  *  @returns EINVAL if the stored packet address is not the an_addr_t.
    119  *  @returns EINVAL if the packet does not contain any data.
    120  *  @returns NO_DATA if the packet content is shorter than the user datagram header.
    121  *  @returns ENOMEM if there is not enough memory left.
    122  *  @returns EADDRNOTAVAIL if the destination socket does not exist.
    123  *  @returns Other error codes as defined for the ip_client_process_packet() function.
    124  */
    125 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error);
    126 
    127 /** Releases the packet and returns the result.
    128  *  @param[in] packet The packet queue to be released.
    129  *  @param[in] result The result to be returned.
    130  *  @return The result parameter.
    131  */
    132 int udp_release_and_return(packet_t packet, int result);
    133 
    134 /** @name Socket messages processing functions
    135  */
    136 /*@{*/
    137 
    138 /** Processes the socket client messages.
    139  *  Runs until the client module disconnects.
    140  *  @param[in] callid The message identifier.
    141  *  @param[in] call The message parameters.
    142  *  @returns EOK on success.
    143  *  @see socket.h
    144  */
    145 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    146 
    147 /** Sends data from the socket to the remote address.
    148  *  Binds the socket to a free port if not already connected/bound.
    149  *  Handles the NET_SOCKET_SENDTO message.
    150  *  Supports AF_INET and AF_INET6 address families.
    151  *  @param[in,out] local_sockets The application local sockets.
    152  *  @param[in] socket_id Socket identifier.
    153  *  @param[in] addr The destination address.
    154  *  @param[in] addrlen The address length.
    155  *  @param[in] fragments The number of data fragments.
    156  *  @param[out] data_fragment_size The data fragment size in bytes.
    157  *  @param[in] flags Various send flags.
    158  *  @returns EOK on success.
    159  *  @returns EAFNOTSUPPORT if the address family is not supported.
    160  *  @returns ENOTSOCK if the socket is not found.
    161  *  @returns EINVAL if the address is invalid.
    162  *  @returns ENOTCONN if the sending socket is not and cannot be bound.
    163  *  @returns ENOMEM if there is not enough memory left.
    164  *  @returns Other error codes as defined for the socket_read_packet_data() function.
    165  *  @returns Other error codes as defined for the ip_client_prepare_packet() function.
    166  *  @returns Other error codes as defined for the ip_send_msg() function.
    167  */
    168 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);
    169 
    170 /** Receives data to the socket.
    171  *  Handles the NET_SOCKET_RECVFROM message.
    172  *  Replies the source address as well.
    173  *  @param[in] local_sockets The application local sockets.
    174  *  @param[in] socket_id Socket identifier.
    175  *  @param[in] flags Various receive flags.
    176  *  @param[out] addrlen The source address length.
    177  *  @returns The number of bytes received.
    178  *  @returns ENOTSOCK if the socket is not found.
    179  *  @returns NO_DATA if there are no received packets or data.
    180  *  @returns ENOMEM if there is not enough memory left.
    181  *  @returns EINVAL if the received address is not an IP address.
    182  *  @returns Other error codes as defined for the packet_translate() function.
    183  *  @returns Other error codes as defined for the data_reply() function.
    184  */
    185 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen);
    186 
    187 /*@}*/
    188 
    189 /** UDP global data.
    190  */
    191 udp_globals_t   udp_globals;
    192 
    193 int udp_initialize(async_client_conn_t client_connection){
    194         ERROR_DECLARE;
    195 
    196         measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}};
    197         measured_string_ref configuration;
     92/** UDP global data.  */
     93udp_globals_t udp_globals;
     94
     95/** Initializes the UDP module.
     96 *
     97 * @param[in] client_connection The client connection processing function. The
     98 *                      module skeleton propagates its own one.
     99 * @return              EOK on success.
     100 * @return              ENOMEM if there is not enough memory left.
     101 */
     102int udp_initialize(async_client_conn_t client_connection)
     103{
     104        measured_string_t names[] = {
     105                {
     106                        (char *) "UDP_CHECKSUM_COMPUTING",
     107                        22
     108                },
     109                {
     110                        (char *) "UDP_AUTOBINDING",
     111                        15
     112                }
     113        };
     114        measured_string_t *configuration;
    198115        size_t count = sizeof(names) / sizeof(measured_string_t);
    199         char * data;
     116        char *data;
     117        int rc;
    200118
    201119        fibril_rwlock_initialize(&udp_globals.lock);
    202120        fibril_rwlock_write_lock(&udp_globals.lock);
    203         udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
    204         udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg);
    205         if(udp_globals.ip_phone < 0){
     121
     122        udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
     123            ICMP_CONNECT_TIMEOUT);
     124       
     125        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
     126            SERVICE_UDP, client_connection);
     127        if (udp_globals.ip_phone < 0) {
     128                fibril_rwlock_write_unlock(&udp_globals.lock);
    206129                return udp_globals.ip_phone;
    207130        }
    208         // read default packet dimensions
    209         ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
    210         ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets));
    211         if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){
     131
     132        /* Read default packet dimensions */
     133        rc = ip_packet_size_req(udp_globals.ip_phone, -1,
     134            &udp_globals.packet_dimension);
     135        if (rc != EOK) {
     136                fibril_rwlock_write_unlock(&udp_globals.lock);
     137                return rc;
     138        }
     139       
     140        rc = socket_ports_initialize(&udp_globals.sockets);
     141        if (rc != EOK) {
     142                fibril_rwlock_write_unlock(&udp_globals.lock);
     143                return rc;
     144        }
     145       
     146        rc = packet_dimensions_initialize(&udp_globals.dimensions);
     147        if (rc != EOK) {
    212148                socket_ports_destroy(&udp_globals.sockets);
    213                 return ERROR_CODE;
    214         }
     149                fibril_rwlock_write_unlock(&udp_globals.lock);
     150                return rc;
     151        }
     152       
    215153        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
    216154        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    217155        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    218         // get configuration
     156
    219157        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    220158        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
     159
     160        /* Get configuration */
    221161        configuration = &names[0];
    222         ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, count, &data));
    223         if(configuration){
    224                 if(configuration[0].value){
    225                         udp_globals.checksum_computing = (configuration[0].value[0] == 'y');
    226                 }
    227                 if(configuration[1].value){
    228                         udp_globals.autobinding = (configuration[1].value[0] == 'y');
    229                 }
     162        rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
     163            &data);
     164        if (rc != EOK) {
     165                socket_ports_destroy(&udp_globals.sockets);
     166                fibril_rwlock_write_unlock(&udp_globals.lock);
     167                return rc;
     168        }
     169       
     170        if (configuration) {
     171                if (configuration[0].value)
     172                        udp_globals.checksum_computing =
     173                            (configuration[0].value[0] == 'y');
     174               
     175                if (configuration[1].value)
     176                        udp_globals.autobinding =
     177                            (configuration[1].value[0] == 'y');
     178
    230179                net_free_settings(configuration, data);
    231180        }
     181
    232182        fibril_rwlock_write_unlock(&udp_globals.lock);
    233183        return EOK;
    234184}
    235185
    236 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
    237         int result;
    238 
    239         fibril_rwlock_write_lock(&udp_globals.lock);
    240         result = udp_process_packet(device_id, packet, error);
    241         if(result != EOK){
    242                 fibril_rwlock_write_unlock(&udp_globals.lock);
    243         }
    244 
     186/** Releases the packet and returns the result.
     187 *
     188 * @param[in] packet    The packet queue to be released.
     189 * @param[in] result    The result to be returned.
     190 * @return              The result parameter.
     191 */
     192static int udp_release_and_return(packet_t *packet, int result)
     193{
     194        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    245195        return result;
    246196}
    247197
    248 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){
    249         ERROR_DECLARE;
    250 
     198/** Processes the received UDP packet queue.
     199 *
     200 * Notifies the destination socket application.
     201 * Releases the packet on error or sends an ICMP error notification.
     202 *
     203 * @param[in] device_id The receiving device identifier.
     204 * @param[in,out] packet The received packet queue.
     205 * @param[in] error     The packet error reporting service. Prefixes the
     206 *                      received packet.
     207 * @return              EOK on success.
     208 * @return              EINVAL if the packet is not valid.
     209 * @return              EINVAL if the stored packet address is not the
     210 *                      an_addr_t.
     211 * @return              EINVAL if the packet does not contain any data.
     212 * @return              NO_DATA if the packet content is shorter than the user
     213 *                      datagram header.
     214 * @return              ENOMEM if there is not enough memory left.
     215 * @return              EADDRNOTAVAIL if the destination socket does not exist.
     216 * @return              Other error codes as defined for the
     217 *                      ip_client_process_packet() function.
     218 */
     219static int udp_process_packet(device_id_t device_id, packet_t *packet,
     220    services_t error)
     221{
    251222        size_t length;
    252223        size_t offset;
    253224        int result;
    254         udp_header_ref header;
    255         socket_core_ref socket;
    256         packet_t next_packet;
     225        udp_header_t *header;
     226        socket_core_t *socket;
     227        packet_t *next_packet;
    257228        size_t total_length;
    258229        uint32_t checksum;
    259230        int fragments;
    260         packet_t tmp_packet;
     231        packet_t *tmp_packet;
    261232        icmp_type_t type;
    262233        icmp_code_t code;
    263234        void *ip_header;
    264         struct sockaddr * src;
    265         struct sockaddr * dest;
    266         packet_dimension_ref packet_dimension;
    267 
    268         if(error){
    269                 switch(error){
    270                         case SERVICE_ICMP:
    271                                 // ignore error
    272                                 // length = icmp_client_header_length(packet);
    273                                 // process error
    274                                 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
    275                                 if(result < 0){
    276                                         return udp_release_and_return(packet, result);
    277                                 }
    278                                 length = (size_t) result;
    279                                 if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
    280                                         return udp_release_and_return(packet, ERROR_CODE);
    281                                 }
    282                                 break;
    283                         default:
    284                                 return udp_release_and_return(packet, ENOTSUP);
    285                 }
    286         }
    287         // TODO process received ipopts?
     235        struct sockaddr *src;
     236        struct sockaddr *dest;
     237        packet_dimension_t *packet_dimension;
     238        int rc;
     239
     240        switch (error) {
     241        case SERVICE_NONE:
     242                break;
     243        case SERVICE_ICMP:
     244                /* Ignore error */
     245                // length = icmp_client_header_length(packet);
     246
     247                /* Process error */
     248                result = icmp_client_process_packet(packet, &type,
     249                    &code, NULL, NULL);
     250                if (result < 0)
     251                        return udp_release_and_return(packet, result);
     252                length = (size_t) result;
     253                rc = packet_trim(packet, length, 0);
     254                if (rc != EOK)
     255                        return udp_release_and_return(packet, rc);
     256                break;
     257        default:
     258                return udp_release_and_return(packet, ENOTSUP);
     259        }
     260
     261        /* TODO process received ipopts? */
    288262        result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
    289         if(result < 0){
     263        if (result < 0)
    290264                return udp_release_and_return(packet, result);
    291         }
    292265        offset = (size_t) result;
    293266
    294267        length = packet_get_data_length(packet);
    295         if(length <= 0){
     268        if (length <= 0)
    296269                return udp_release_and_return(packet, EINVAL);
    297         }
    298         if(length < UDP_HEADER_SIZE + offset){
     270        if (length < UDP_HEADER_SIZE + offset)
    299271                return udp_release_and_return(packet, NO_DATA);
    300         }
    301 
    302         // trim all but UDP header
    303         if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
    304                 return udp_release_and_return(packet, ERROR_CODE);
    305         }
    306 
    307         // get udp header
    308         header = (udp_header_ref) packet_get_data(packet);
    309         if(! header){
     272
     273        /* Trim all but UDP header */
     274        rc = packet_trim(packet, offset, 0);
     275        if (rc != EOK)
     276                return udp_release_and_return(packet, rc);
     277
     278        /* Get UDP header */
     279        header = (udp_header_t *) packet_get_data(packet);
     280        if (!header)
    310281                return udp_release_and_return(packet, NO_DATA);
    311         }
    312         // find the destination socket
    313         socket = socket_port_find(&udp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
    314         if(! socket){
    315                 if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
    316                         icmp_destination_unreachable_msg(udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet);
     282
     283        /* Find the destination socket */
     284        socket = socket_port_find(&udp_globals.sockets,
     285        ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     286        if (!socket) {
     287                if (tl_prepare_icmp_packet(udp_globals.net_phone,
     288                    udp_globals.icmp_phone, packet, error) == EOK) {
     289                        icmp_destination_unreachable_msg(udp_globals.icmp_phone,
     290                            ICMP_PORT_UNREACH, 0, packet);
    317291                }
    318292                return EADDRNOTAVAIL;
    319293        }
    320294
    321         // count the received packet fragments
     295        /* Count the received packet fragments */
    322296        next_packet = packet;
    323297        fragments = 0;
    324298        total_length = ntohs(header->total_length);
    325         // compute header checksum if set
    326         if(header->checksum && (! error)){
    327                 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
    328                 if(result <= 0){
     299
     300        /* Compute header checksum if set */
     301        if (header->checksum && !error) {
     302                result = packet_get_addr(packet, (uint8_t **) &src,
     303                    (uint8_t **) &dest);
     304                if (result <= 0)
    329305                        return udp_release_and_return(packet, result);
    330                 }
    331                 if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){
    332                         return udp_release_and_return(packet, ERROR_CODE);
    333                 }else{
     306               
     307                rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest,
     308                    result, total_length, &ip_header, &length);
     309                if (rc != EOK) {
     310                        return udp_release_and_return(packet, rc);
     311                } else {
    334312                        checksum = compute_checksum(0, ip_header, length);
    335                         // the udp header checksum will be added with the first fragment later
     313                        /*
     314                         * The udp header checksum will be added with the first
     315                         * fragment later.
     316                         */
    336317                        free(ip_header);
    337318                }
    338         }else{
     319        } else {
    339320                header->checksum = 0;
    340321                checksum = 0;
    341322        }
    342323
    343         do{
    344                 ++ fragments;
     324        do {
     325                fragments++;
    345326                length = packet_get_data_length(next_packet);
    346                 if(length <= 0){
     327                if (length <= 0)
    347328                        return udp_release_and_return(packet, NO_DATA);
    348                 }
    349                 if(total_length < length){
    350                         if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - total_length))){
    351                                 return udp_release_and_return(packet, ERROR_CODE);
     329
     330                if (total_length < length) {
     331                        rc = packet_trim(next_packet, 0, length - total_length);
     332                        if (rc != EOK)
     333                                return udp_release_and_return(packet, rc);
     334
     335                        /* Add partial checksum if set */
     336                        if (header->checksum) {
     337                                checksum = compute_checksum(checksum,
     338                                    packet_get_data(packet),
     339                                    packet_get_data_length(packet));
    352340                        }
    353                         // add partial checksum if set
    354                         if(header->checksum){
    355                                 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
    356                         }
    357                         // relese the rest of the packet fragments
     341
     342                        /* Relese the rest of the packet fragments */
    358343                        tmp_packet = pq_next(next_packet);
    359                         while(tmp_packet){
     344                        while (tmp_packet) {
    360345                                next_packet = pq_detach(tmp_packet);
    361                                 pq_release_remote(udp_globals.net_phone, packet_get_id(tmp_packet));
     346                                pq_release_remote(udp_globals.net_phone,
     347                                    packet_get_id(tmp_packet));
    362348                                tmp_packet = next_packet;
    363349                        }
    364                         // exit the loop
     350
     351                        /* Exit the loop */
    365352                        break;
    366353                }
    367354                total_length -= length;
    368                 // add partial checksum if set
    369                 if(header->checksum){
    370                         checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
     355
     356                /* Add partial checksum if set */
     357                if (header->checksum) {
     358                        checksum = compute_checksum(checksum,
     359                            packet_get_data(packet),
     360                            packet_get_data_length(packet));
    371361                }
    372         }while((next_packet = pq_next(next_packet)) && (total_length > 0));
    373 
    374         // check checksum
    375         if(header->checksum){
    376                 if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){
    377                         if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
    378                                 // checksum error ICMP
    379                                 icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
     362
     363        } while ((next_packet = pq_next(next_packet)) && (total_length > 0));
     364
     365        /* Verify checksum */
     366        if (header->checksum) {
     367                if (flip_checksum(compact_checksum(checksum)) !=
     368                    IP_CHECKSUM_ZERO) {
     369                        if (tl_prepare_icmp_packet(udp_globals.net_phone,
     370                            udp_globals.icmp_phone, packet, error) == EOK) {
     371                                /* Checksum error ICMP */
     372                                icmp_parameter_problem_msg(
     373                                    udp_globals.icmp_phone, ICMP_PARAM_POINTER,
     374                                    ((size_t) ((void *) &header->checksum)) -
     375                                    ((size_t) ((void *) header)), packet);
    380376                        }
    381377                        return EINVAL;
     
    383379        }
    384380
    385         // queue the received packet
    386         if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE))
    387             || ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension))){
    388                 return udp_release_and_return(packet, ERROR_CODE);
    389         }
    390 
    391         // notify the destination socket
     381        /* Queue the received packet */
     382        rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
     383            SOCKET_MAX_RECEIVED_SIZE);
     384        if (rc != EOK)
     385                return udp_release_and_return(packet, rc);
     386               
     387        rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
     388            &udp_globals.dimensions, device_id, &packet_dimension);
     389        if (rc != EOK)
     390                return udp_release_and_return(packet, rc);
     391
     392        /* Notify the destination socket */
    392393        fibril_rwlock_write_unlock(&udp_globals.lock);
    393         async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments);
     394        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
     395            (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,
     396            (ipcarg_t) fragments);
     397
    394398        return EOK;
    395399}
    396400
    397 int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    398         ERROR_DECLARE;
    399 
    400         packet_t packet;
    401 
    402         *answer_count = 0;
    403         switch(IPC_GET_METHOD(*call)){
    404                 case NET_TL_RECEIVED:
    405                         if(! ERROR_OCCURRED(packet_translate_remote(udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    406                                 ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_UDP, IPC_GET_ERROR(call));
    407                         }
    408                         return ERROR_CODE;
    409                 case IPC_M_CONNECT_TO_ME:
    410                         return udp_process_client_messages(callid, * call);
    411         }
    412         return ENOTSUP;
     401/** Processes the received UDP packet queue.
     402 *
     403 * Is used as an entry point from the underlying IP module.
     404 * Locks the global lock and calls udp_process_packet() function.
     405 *
     406 * @param[in] device_id The receiving device identifier.
     407 * @param[in,out] packet The received packet queue.
     408 * @param receiver      The target service. Ignored parameter.
     409 * @param[in] error     The packet error reporting service. Prefixes the
     410 *                      received packet.
     411 * @return              EOK on success.
     412 * @return              Other error codes as defined for the
     413 *                      udp_process_packet() function.
     414 */
     415static int udp_received_msg(device_id_t device_id, packet_t *packet,
     416    services_t receiver, services_t error)
     417{
     418        int result;
     419
     420        fibril_rwlock_write_lock(&udp_globals.lock);
     421        result = udp_process_packet(device_id, packet, error);
     422        if (result != EOK)
     423                fibril_rwlock_write_unlock(&udp_globals.lock);
     424
     425        return result;
    413426}
    414427
    415 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
    416         int res;
    417         bool keep_on_going = true;
    418         socket_cores_t local_sockets;
    419         int app_phone = IPC_GET_PHONE(&call);
    420         struct sockaddr * addr;
    421         int socket_id;
    422         size_t addrlen;
    423         size_t size;
    424         ipc_call_t answer;
    425         int answer_count;
    426         packet_dimension_ref packet_dimension;
    427 
    428         /*
    429          * Accept the connection
    430          *  - Answer the first IPC_M_CONNECT_TO_ME call.
    431          */
    432         res = EOK;
    433         answer_count = 0;
    434 
    435         // The client connection is only in one fibril and therefore no additional locks are needed.
    436 
    437         socket_cores_initialize(&local_sockets);
    438 
    439         while(keep_on_going){
    440 
    441                 // answer the call
    442                 answer_call(callid, res, &answer, answer_count);
    443 
    444                 // refresh data
    445                 refresh_answer(&answer, &answer_count);
    446 
    447                 // get the next call
    448                 callid = async_get_call(&call);
    449 
    450                 // process the call
    451                 switch(IPC_GET_METHOD(call)){
    452                         case IPC_M_PHONE_HUNGUP:
    453                                 keep_on_going = false;
    454                                 res = EHANGUP;
    455                                 break;
    456                         case NET_SOCKET:
    457                                 socket_id = SOCKET_GET_SOCKET_ID(call);
    458                                 res = socket_create(&local_sockets, app_phone, NULL, &socket_id);
    459                                 SOCKET_SET_SOCKET_ID(answer, socket_id);
    460 
    461                                 if(res == EOK){
    462                                         if (tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
    463                                                 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, packet_dimension->content);
    464                                         }
    465 //                                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_UDP_FRAGMENT_SIZE);
    466                                         SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
    467                                         answer_count = 3;
    468                                 }
    469                                 break;
    470                         case NET_SOCKET_BIND:
    471                                 res = data_receive((void **) &addr, &addrlen);
    472                                 if(res == EOK){
    473                                         fibril_rwlock_write_lock(&udp_globals.lock);
    474                                         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);
    475                                         fibril_rwlock_write_unlock(&udp_globals.lock);
    476                                         free(addr);
    477                                 }
    478                                 break;
    479                         case NET_SOCKET_SENDTO:
    480                                 res = data_receive((void **) &addr, &addrlen);
    481                                 if(res == EOK){
    482                                         fibril_rwlock_write_lock(&udp_globals.lock);
    483                                         res = udp_sendto_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS(call), &size, SOCKET_GET_FLAGS(call));
    484                                         SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
    485                                         if(res != EOK){
    486                                                 fibril_rwlock_write_unlock(&udp_globals.lock);
    487                                         }else{
    488                                                 answer_count = 2;
    489                                         }
    490                                         free(addr);
    491                                 }
    492                                 break;
    493                         case NET_SOCKET_RECVFROM:
    494                                 fibril_rwlock_write_lock(&udp_globals.lock);
    495                                 res = udp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen);
    496                                 fibril_rwlock_write_unlock(&udp_globals.lock);
    497                                 if(res > 0){
    498                                         SOCKET_SET_READ_DATA_LENGTH(answer, res);
    499                                         SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
    500                                         answer_count = 3;
    501                                         res = EOK;
    502                                 }
    503                                 break;
    504                         case NET_SOCKET_CLOSE:
    505                                 fibril_rwlock_write_lock(&udp_globals.lock);
    506                                 res = socket_destroy(udp_globals.net_phone, SOCKET_GET_SOCKET_ID(call), &local_sockets, &udp_globals.sockets, NULL);
    507                                 fibril_rwlock_write_unlock(&udp_globals.lock);
    508                                 break;
    509                         case NET_SOCKET_GETSOCKOPT:
    510                         case NET_SOCKET_SETSOCKOPT:
    511                         default:
    512                                 res = ENOTSUP;
    513                                 break;
    514                 }
    515         }
    516 
    517         // release the application phone
    518         ipc_hangup(app_phone);
    519 
    520         // release all local sockets
    521         socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL);
    522 
    523         return res;
    524 }
    525 
    526 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){
    527         ERROR_DECLARE;
    528 
    529         socket_core_ref socket;
    530         packet_t packet;
    531         packet_t next_packet;
    532         udp_header_ref header;
     428/** Sends data from the socket to the remote address.
     429 *
     430 * Binds the socket to a free port if not already connected/bound.
     431 * Handles the NET_SOCKET_SENDTO message.
     432 * Supports AF_INET and AF_INET6 address families.
     433 *
     434 * @param[in,out] local_sockets The application local sockets.
     435 * @param[in] socket_id Socket identifier.
     436 * @param[in] addr      The destination address.
     437 * @param[in] addrlen   The address length.
     438 * @param[in] fragments The number of data fragments.
     439 * @param[out] data_fragment_size The data fragment size in bytes.
     440 * @param[in] flags     Various send flags.
     441 * @return              EOK on success.
     442 * @return              EAFNOTSUPPORT if the address family is not supported.
     443 * @return              ENOTSOCK if the socket is not found.
     444 * @return              EINVAL if the address is invalid.
     445 * @return              ENOTCONN if the sending socket is not and cannot be
     446 *                      bound.
     447 * @return              ENOMEM if there is not enough memory left.
     448 * @return              Other error codes as defined for the
     449 *                      socket_read_packet_data() function.
     450 * @return              Other error codes as defined for the
     451 *                      ip_client_prepare_packet() function.
     452 * @return              Other error codes as defined for the ip_send_msg()
     453 *                      function.
     454 */
     455static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id,
     456    const struct sockaddr *addr, socklen_t addrlen, int fragments,
     457    size_t *data_fragment_size, int flags)
     458{
     459        socket_core_t *socket;
     460        packet_t *packet;
     461        packet_t *next_packet;
     462        udp_header_t *header;
    533463        int index;
    534464        size_t total_length;
     
    539469        size_t headerlen;
    540470        device_id_t device_id;
    541         packet_dimension_ref packet_dimension;
    542 
    543         ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port));
     471        packet_dimension_t *packet_dimension;
     472        int rc;
     473       
     474        rc = tl_get_address_port(addr, addrlen, &dest_port);
     475        if (rc != EOK)
     476                return rc;
    544477
    545478        socket = socket_cores_find(local_sockets, socket_id);
    546         if(! socket){
     479        if (!socket)
    547480                return ENOTSOCK;
    548         }
    549 
    550         if((socket->port <= 0) && udp_globals.autobinding){
    551                 // bind the socket to a random free port if not bound
    552 //              do{
    553                         // try to find a free port
    554 //                      fibril_rwlock_read_unlock(&udp_globals.lock);
    555 //                      fibril_rwlock_write_lock(&udp_globals.lock);
    556                         // might be changed in the meantime
    557 //                      if(socket->port <= 0){
    558                                 if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){
    559 //                                      fibril_rwlock_write_unlock(&udp_globals.lock);
    560 //                                      fibril_rwlock_read_lock(&udp_globals.lock);
    561                                         return ERROR_CODE;
    562                                 }
    563                                 // set the next port as the search starting port number
    564                                 udp_globals.last_used_port = socket->port;
    565 //                      }
    566 //                      fibril_rwlock_write_unlock(&udp_globals.lock);
    567 //                      fibril_rwlock_read_lock(&udp_globals.lock);
    568                         // might be changed in the meantime
    569 //              }while(socket->port <= 0);
    570         }
    571 
    572         if(udp_globals.checksum_computing){
    573                 if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){
    574                         return udp_release_and_return(packet, ERROR_CODE);
    575                 }
    576                 // get the device packet dimension
    577 //              ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension));
    578         }
    579 //      }else{
    580                 // do not ask all the time
    581                 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
     481
     482        if ((socket->port <= 0) && udp_globals.autobinding) {
     483                /* Bind the socket to a random free port if not bound */
     484                rc = socket_bind_free_port(&udp_globals.sockets, socket,
     485                    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
     486                    udp_globals.last_used_port);
     487                if (rc != EOK)
     488                        return rc;
     489                /* Set the next port as the search starting port number */
     490                udp_globals.last_used_port = socket->port;
     491        }
     492
     493        if (udp_globals.checksum_computing) {
     494                rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr,
     495                    addrlen, &device_id, &ip_header, &headerlen);
     496                if (rc != EOK)
     497                        return rc;
     498                /* Get the device packet dimension */
     499//              rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
     500//                  &udp_globals.dimensions, device_id, &packet_dimension);
     501//              if (rc != EOK)
     502//                      return rc;
     503        }
     504//      } else {
     505                /* Do not ask all the time */
     506                rc = ip_packet_size_req(udp_globals.ip_phone, -1,
     507                    &udp_globals.packet_dimension);
     508                if (rc != EOK)
     509                        return rc;
    582510                packet_dimension = &udp_globals.packet_dimension;
    583511//      }
    584512
    585         // read the first packet fragment
    586         result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
    587         if(result < 0){
     513        /* Read the first packet fragment */
     514        result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
     515            UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
     516        if (result < 0)
    588517                return result;
    589         }
     518
    590519        total_length = (size_t) result;
    591         if(udp_globals.checksum_computing){
    592                 checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet));
    593         }else{
     520        if (udp_globals.checksum_computing)
     521                checksum = compute_checksum(0, packet_get_data(packet),
     522                    packet_get_data_length(packet));
     523        else
    594524                checksum = 0;
    595         }
    596         // prefix the udp header
     525
     526        /* Prefix the UDP header */
    597527        header = PACKET_PREFIX(packet, udp_header_t);
    598         if(! header){
     528        if (!header)
    599529                return udp_release_and_return(packet, ENOMEM);
    600         }
     530
    601531        bzero(header, sizeof(*header));
    602         // read the rest of the packet fragments
    603         for(index = 1; index < fragments; ++ index){
    604                 result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen);
    605                 if(result < 0){
     532
     533        /* Read the rest of the packet fragments */
     534        for (index = 1; index < fragments; index++) {
     535                result = tl_socket_read_packet_data(udp_globals.net_phone,
     536                    &next_packet, 0, packet_dimension, addr, addrlen);
     537                if (result < 0)
    606538                        return udp_release_and_return(packet, result);
     539
     540                rc = pq_add(&packet, next_packet, index, 0);
     541                if (rc != EOK)
     542                        return udp_release_and_return(packet, rc);
     543
     544                total_length += (size_t) result;
     545                if (udp_globals.checksum_computing) {
     546                        checksum = compute_checksum(checksum,
     547                            packet_get_data(next_packet),
     548                            packet_get_data_length(next_packet));
    607549                }
    608                 if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){
    609                         return udp_release_and_return(packet, ERROR_CODE);
    610                 }
    611                 total_length += (size_t) result;
    612                 if(udp_globals.checksum_computing){
    613                         checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet));
    614                 }
    615         }
    616         // set the udp header
     550        }
     551
     552        /* Set the UDP header */
    617553        header->source_port = htons((socket->port > 0) ? socket->port : 0);
    618554        header->destination_port = htons(dest_port);
    619555        header->total_length = htons(total_length + sizeof(*header));
    620556        header->checksum = 0;
    621         if(udp_globals.checksum_computing){
    622                 // update the pseudo header
    623                 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
     557
     558        if (udp_globals.checksum_computing) {
     559                /* Update the pseudo header */
     560                rc = ip_client_set_pseudo_header_data_length(ip_header,
     561                    headerlen, total_length + UDP_HEADER_SIZE);
     562                if (rc != EOK) {
    624563                        free(ip_header);
    625                         return udp_release_and_return(packet, ERROR_CODE);
     564                        return udp_release_and_return(packet, rc);
    626565                }
    627                 // finish the checksum computation
     566
     567                /* Finish the checksum computation */
    628568                checksum = compute_checksum(checksum, ip_header, headerlen);
    629                 checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header));
    630                 header->checksum = htons(flip_checksum(compact_checksum(checksum)));
     569                checksum = compute_checksum(checksum, (uint8_t *) header,
     570                    sizeof(*header));
     571                header->checksum =
     572                    htons(flip_checksum(compact_checksum(checksum)));
    631573                free(ip_header);
    632         }else{
     574        } else {
    633575                device_id = DEVICE_INVALID_ID;
    634576        }
    635         // prepare the first packet fragment
    636         if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){
    637                 return udp_release_and_return(packet, ERROR_CODE);
    638         }
    639         // send the packet
     577
     578        /* Prepare the first packet fragment */
     579        rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0);
     580        if (rc != EOK)
     581                return udp_release_and_return(packet, rc);
     582
     583        /* Release the UDP global lock on success. */
    640584        fibril_rwlock_write_unlock(&udp_globals.lock);
     585
     586        /* Send the packet */
    641587        ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
     588
    642589        return EOK;
    643590}
    644591
    645 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
    646         ERROR_DECLARE;
    647 
    648         socket_core_ref socket;
     592/** Receives data to the socket.
     593 *
     594 * Handles the NET_SOCKET_RECVFROM message.
     595 * Replies the source address as well.
     596 *
     597 * @param[in] local_sockets The application local sockets.
     598 * @param[in] socket_id Socket identifier.
     599 * @param[in] flags     Various receive flags.
     600 * @param[out] addrlen  The source address length.
     601 * @return              The number of bytes received.
     602 * @return              ENOTSOCK if the socket is not found.
     603 * @return              NO_DATA if there are no received packets or data.
     604 * @return              ENOMEM if there is not enough memory left.
     605 * @return              EINVAL if the received address is not an IP address.
     606 * @return              Other error codes as defined for the packet_translate()
     607 *                      function.
     608 * @return              Other error codes as defined for the data_reply()
     609 *                      function.
     610 */
     611static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
     612    int flags, size_t *addrlen)
     613{
     614        socket_core_t *socket;
    649615        int packet_id;
    650         packet_t packet;
    651         udp_header_ref header;
    652         struct sockaddr * addr;
     616        packet_t *packet;
     617        udp_header_t *header;
     618        struct sockaddr *addr;
    653619        size_t length;
    654         uint8_t * data;
     620        uint8_t *data;
    655621        int result;
    656 
    657         // find the socket
     622        int rc;
     623
     624        /* Find the socket */
    658625        socket = socket_cores_find(local_sockets, socket_id);
    659         if(! socket){
     626        if (!socket)
    660627                return ENOTSOCK;
    661         }
    662         // get the next received packet
     628
     629        /* Get the next received packet */
    663630        packet_id = dyn_fifo_value(&socket->received);
    664         if(packet_id < 0){
     631        if (packet_id < 0)
    665632                return NO_DATA;
    666         }
    667         ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, packet_id));
    668         // get udp header
     633       
     634        rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id);
     635        if (rc != EOK) {
     636                (void) dyn_fifo_pop(&socket->received);
     637                return rc;
     638        }
     639
     640        /* Get UDP header */
    669641        data = packet_get_data(packet);
    670         if(! data){
    671                 pq_release_remote(udp_globals.net_phone, packet_id);
    672                 return NO_DATA;
    673         }
    674         header = (udp_header_ref) data;
    675 
    676         // set the source address port
     642        if (!data) {
     643                (void) dyn_fifo_pop(&socket->received);
     644                return udp_release_and_return(packet, NO_DATA);
     645        }
     646        header = (udp_header_t *) data;
     647
     648        /* Set the source address port */
    677649        result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
    678         if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){
    679                 pq_release_remote(udp_globals.net_phone, packet_id);
    680                 return ERROR_CODE;
     650        rc = tl_set_address_port(addr, result, ntohs(header->source_port));
     651        if (rc != EOK) {
     652                (void) dyn_fifo_pop(&socket->received);
     653                return udp_release_and_return(packet, rc);
    681654        }
    682655        *addrlen = (size_t) result;
    683         // send the source address
    684         ERROR_PROPAGATE(data_reply(addr, * addrlen));
    685 
    686         // trim the header
    687         ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));
    688 
    689         // reply the packets
    690         ERROR_PROPAGATE(socket_reply_packets(packet, &length));
    691 
    692         // release the packet
    693         dyn_fifo_pop(&socket->received);
    694         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    695         // return the total length
    696         return (int) length;
     656
     657        /* Send the source address */
     658        rc = data_reply(addr, *addrlen);
     659        switch (rc) {
     660        case EOK:
     661                break;
     662        case EOVERFLOW:
     663                return rc;
     664        default:
     665                (void) dyn_fifo_pop(&socket->received);
     666                return udp_release_and_return(packet, rc);
     667        }
     668
     669        /* Trim the header */
     670        rc = packet_trim(packet, UDP_HEADER_SIZE, 0);
     671        if (rc != EOK) {
     672                (void) dyn_fifo_pop(&socket->received);
     673                return udp_release_and_return(packet, rc);
     674        }
     675
     676        /* Reply the packets */
     677        rc = socket_reply_packets(packet, &length);
     678        switch (rc) {
     679        case EOK:
     680                break;
     681        case EOVERFLOW:
     682                return rc;
     683        default:
     684                (void) dyn_fifo_pop(&socket->received);
     685                return udp_release_and_return(packet, rc);
     686        }
     687
     688        (void) dyn_fifo_pop(&socket->received);
     689
     690        /* Release the packet and return the total length */
     691        return udp_release_and_return(packet, (int) length);
    697692}
    698693
    699 int udp_release_and_return(packet_t packet, int result){
    700         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    701         return result;
     694/** Processes the socket client messages.
     695 *
     696 * Runs until the client module disconnects.
     697 *
     698 * @param[in] callid    The message identifier.
     699 * @param[in] call      The message parameters.
     700 * @return              EOK on success.
     701 *
     702 * @see socket.h
     703 */
     704static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     705{
     706        int res;
     707        bool keep_on_going = true;
     708        socket_cores_t local_sockets;
     709        int app_phone = IPC_GET_PHONE(&call);
     710        struct sockaddr *addr;
     711        int socket_id;
     712        size_t addrlen;
     713        size_t size = 0;
     714        ipc_call_t answer;
     715        int answer_count;
     716        packet_dimension_t *packet_dimension;
     717
     718        /*
     719         * Accept the connection
     720         *  - Answer the first IPC_M_CONNECT_TO_ME call.
     721         */
     722        res = EOK;
     723        answer_count = 0;
     724
     725        /*
     726         * The client connection is only in one fibril and therefore no
     727         * additional locks are needed.
     728         */
     729
     730        socket_cores_initialize(&local_sockets);
     731
     732        while (keep_on_going) {
     733
     734                /* Answer the call */
     735                answer_call(callid, res, &answer, answer_count);
     736
     737                /* Refresh data */
     738                refresh_answer(&answer, &answer_count);
     739
     740                /* Get the next call */
     741                callid = async_get_call(&call);
     742
     743                /* Process the call */
     744                switch (IPC_GET_METHOD(call)) {
     745                case IPC_M_PHONE_HUNGUP:
     746                        keep_on_going = false;
     747                        res = EHANGUP;
     748                        break;
     749
     750                case NET_SOCKET:
     751                        socket_id = SOCKET_GET_SOCKET_ID(call);
     752                        res = socket_create(&local_sockets, app_phone, NULL,
     753                            &socket_id);
     754                        SOCKET_SET_SOCKET_ID(answer, socket_id);
     755
     756                        if (res != EOK)
     757                                break;
     758                       
     759                        if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
     760                            &udp_globals.dimensions, DEVICE_INVALID_ID,
     761                            &packet_dimension) == EOK) {
     762                                SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     763                                    packet_dimension->content);
     764                        }
     765
     766//                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     767//                          MAX_UDP_FRAGMENT_SIZE);
     768                        SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
     769                        answer_count = 3;
     770                        break;
     771
     772                case NET_SOCKET_BIND:
     773                        res = data_receive((void **) &addr, &addrlen);
     774                        if (res != EOK)
     775                                break;
     776                        fibril_rwlock_write_lock(&udp_globals.lock);
     777                        res = socket_bind(&local_sockets, &udp_globals.sockets,
     778                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     779                            UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
     780                            udp_globals.last_used_port);
     781                        fibril_rwlock_write_unlock(&udp_globals.lock);
     782                        free(addr);
     783                        break;
     784
     785                case NET_SOCKET_SENDTO:
     786                        res = data_receive((void **) &addr, &addrlen);
     787                        if (res != EOK)
     788                                break;
     789
     790                        fibril_rwlock_write_lock(&udp_globals.lock);
     791                        res = udp_sendto_message(&local_sockets,
     792                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     793                            SOCKET_GET_DATA_FRAGMENTS(call), &size,
     794                            SOCKET_GET_FLAGS(call));
     795                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     796
     797                        if (res != EOK)
     798                                fibril_rwlock_write_unlock(&udp_globals.lock);
     799                        else
     800                                answer_count = 2;
     801                       
     802                        free(addr);
     803                        break;
     804
     805                case NET_SOCKET_RECVFROM:
     806                        fibril_rwlock_write_lock(&udp_globals.lock);
     807                        res = udp_recvfrom_message(&local_sockets,
     808                             SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
     809                             &addrlen);
     810                        fibril_rwlock_write_unlock(&udp_globals.lock);
     811
     812                        if (res <= 0)
     813                                break;
     814
     815                        SOCKET_SET_READ_DATA_LENGTH(answer, res);
     816                        SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
     817                        answer_count = 3;
     818                        res = EOK;
     819                        break;
     820                       
     821                case NET_SOCKET_CLOSE:
     822                        fibril_rwlock_write_lock(&udp_globals.lock);
     823                        res = socket_destroy(udp_globals.net_phone,
     824                            SOCKET_GET_SOCKET_ID(call), &local_sockets,
     825                            &udp_globals.sockets, NULL);
     826                        fibril_rwlock_write_unlock(&udp_globals.lock);
     827                        break;
     828
     829                case NET_SOCKET_GETSOCKOPT:
     830                case NET_SOCKET_SETSOCKOPT:
     831                default:
     832                        res = ENOTSUP;
     833                        break;
     834                }
     835        }
     836
     837        /* Release the application phone */
     838        ipc_hangup(app_phone);
     839
     840        /* Release all local sockets */
     841        socket_cores_release(udp_globals.net_phone, &local_sockets,
     842            &udp_globals.sockets, NULL);
     843
     844        return res;
    702845}
    703846
     847/** Processes the UDP message.
     848 *
     849 * @param[in] callid    The message identifier.
     850 * @param[in] call      The message parameters.
     851 * @param[out] answer   The message answer parameters.
     852 * @param[out] answer_count The last parameter for the actual answer in the
     853 *                      answer parameter.
     854 * @return              EOK on success.
     855 * @return              ENOTSUP if the message is not known.
     856 *
     857 * @see udp_interface.h
     858 * @see IS_NET_UDP_MESSAGE()
     859 */
     860int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     861    ipc_call_t *answer, int *answer_count)
     862{
     863        packet_t *packet;
     864        int rc;
     865
     866        *answer_count = 0;
     867
     868        switch (IPC_GET_METHOD(*call)) {
     869        case NET_TL_RECEIVED:
     870                rc = packet_translate_remote(udp_globals.net_phone, &packet,
     871                    IPC_GET_PACKET(call));
     872                if (rc != EOK)
     873                        return rc;
     874                return udp_received_msg(IPC_GET_DEVICE(call), packet,
     875                    SERVICE_UDP, IPC_GET_ERROR(call));
     876        case IPC_M_CONNECT_TO_ME:
     877                return udp_process_client_messages(callid, * call);
     878        }
     879
     880        return ENOTSUP;
     881}
     882
    704883/** Default thread for new connections.
    705884 *
    706  *  @param[in] iid The initial message identifier.
    707  *  @param[in] icall The initial message call structure.
    708  *
     885 * @param[in] iid       The initial message identifier.
     886 * @param[in] icall     The initial message call structure.
    709887 */
    710888static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     
    716894        ipc_answer_0(iid, EOK);
    717895       
    718         while(true) {
     896        while (true) {
    719897                ipc_call_t answer;
    720898                int answer_count;
     
    731909                    &answer_count);
    732910               
    733                 /* End if said to either by the message or the processing result */
    734                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
     911                /*
     912                 * End if told to either by the message or the processing
     913                 * result.
     914                 */
     915                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     916                    (res == EHANGUP))
    735917                        return;
    736918               
     
    742924/** Starts the module.
    743925 *
    744  *  @param argc The count of the command line arguments. Ignored parameter.
    745  *  @param argv The command line parameters. Ignored parameter.
    746  *
    747  *  @returns EOK on success.
    748  *  @returns Other error codes as defined for each specific module start function.
    749  *
     926 * @return              EOK on success.
     927 * @return              Other error codes as defined for each specific module
     928 *                      start function.
    750929 */
    751930int main(int argc, char *argv[])
    752931{
    753         ERROR_DECLARE;
     932        int rc;
    754933       
    755934        /* Start the module */
    756         if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
    757                 return ERROR_CODE;
    758        
    759         return EOK;
     935        rc = tl_module_start_standalone(tl_client_connection);
     936        return rc;
    760937}
    761938
Note: See TracChangeset for help on using the changeset viewer.