Ignore:
File:
1 edited

Legend:

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

    r8e3a65c r46d4d9f  
    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>
     
    4549#include <ipc/tl.h>
    4650#include <ipc/socket.h>
     51#include <adt/dynamic_fifo.h>
    4752#include <errno.h>
    48 #include <err.h>
    4953
    5054#include <net/socket_codes.h>
     
    5559#include <net/modules.h>
    5660
    57 #include <adt/dynamic_fifo.h>
    5861#include <packet_client.h>
    5962#include <packet_remote.h>
     
    6972#include <tl_interface.h>
    7073
    71 #include "udp.h"
    72 #include "udp_header.h"
    73 #include "udp_module.h"
    74 
    7574/** UDP module name. */
    7675#define NAME    "UDP protocol"
     
    9190#define UDP_FREE_PORTS_END              65535
    9291
    93 /** Processes the received UDP packet queue.
    94  *
    95  *  Is used as an entry point from the underlying IP module.
    96  *  Locks the global lock and calls udp_process_packet() function.
    97  *
    98  *  @param[in] device_id The receiving device identifier.
    99  *  @param[in,out] packet The received packet queue.
    100  *  @param receiver     The target service. Ignored parameter.
    101  *  @param[in] error    The packet error reporting service. Prefixes the
    102  *                      received packet.
    103  *  @returns            EOK on success.
    104  *  @returns            Other error codes as defined for the
    105  *                      udp_process_packet() function.
    106  */
    107 int
    108 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
    109     services_t error);
    110 
    111 /** Processes the received UDP packet queue.
    112  *
    113  *  Notifies the destination socket application.
    114  *  Releases the packet on error or sends an ICMP error notification.
    115  *
    116  *  @param[in] device_id The receiving device identifier.
    117  *  @param[in,out] packet The received packet queue.
    118  *  @param[in] error    The packet error reporting service. Prefixes the
    119  *                      received packet.
    120  *  @returns            EOK on success.
    121  *  @returns            EINVAL if the packet is not valid.
    122  *  @returns            EINVAL if the stored packet address is not the
    123  *                      an_addr_t.
    124  *  @returns            EINVAL if the packet does not contain any data.
    125  *  @returns            NO_DATA if the packet content is shorter than the user
    126  *                      datagram header.
    127  *  @returns            ENOMEM if there is not enough memory left.
    128  *  @returns            EADDRNOTAVAIL if the destination socket does not exist.
    129  *  @returns            Other error codes as defined for the
    130  *                      ip_client_process_packet() function.
    131  */
    132 int
    133 udp_process_packet(device_id_t device_id, packet_t packet, services_t error);
    134 
    135 /** Releases the packet and returns the result.
    136  *
    137  *  @param[in] packet   The packet queue to be released.
    138  *  @param[in] result   The result to be returned.
    139  *  @return             The result parameter.
    140  */
    141 int udp_release_and_return(packet_t packet, int result);
    142 
    143 /** @name Socket messages processing functions
    144  */
    145 /*@{*/
    146 
    147 /** Processes the socket client messages.
    148  *
    149  *  Runs until the client module disconnects.
    150  *
    151  *  @param[in] callid   The message identifier.
    152  *  @param[in] call     The message parameters.
    153  *  @returns            EOK on success.
    154  *  @see                socket.h
    155  */
    156 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    157 
    158 /** Sends data from the socket to the remote address.
    159  *
    160  *  Binds the socket to a free port if not already connected/bound.
    161  *  Handles the NET_SOCKET_SENDTO message.
    162  *  Supports AF_INET and AF_INET6 address families.
    163  *
    164  *  @param[in,out] local_sockets The application local sockets.
    165  *  @param[in] socket_id Socket identifier.
    166  *  @param[in] addr     The destination address.
    167  *  @param[in] addrlen  The address length.
    168  *  @param[in] fragments The number of data fragments.
    169  *  @param[out] data_fragment_size The data fragment size in bytes.
    170  *  @param[in] flags    Various send flags.
    171  *  @returns            EOK on success.
    172  *  @returns            EAFNOTSUPPORT if the address family is not supported.
    173  *  @returns            ENOTSOCK if the socket is not found.
    174  *  @returns            EINVAL if the address is invalid.
    175  *  @returns            ENOTCONN if the sending socket is not and cannot be
    176  *                      bound.
    177  *  @returns            ENOMEM if there is not enough memory left.
    178  *  @returns            Other error codes as defined for the
    179  *                      socket_read_packet_data() function.
    180  *  @returns            Other error codes as defined for the
    181  *                      ip_client_prepare_packet() function.
    182  *  @returns            Other error codes as defined for the ip_send_msg()
    183  *                      function.
    184  */
    185 int
    186 udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    187     const struct sockaddr * addr, socklen_t addrlen, int fragments,
    188     size_t * data_fragment_size, int flags);
    189 
    190 /** Receives data to the socket.
    191  *
    192  *  Handles the NET_SOCKET_RECVFROM message.
    193  *  Replies the source address as well.
    194  *
    195  *  @param[in] local_sockets The application local sockets.
    196  *  @param[in] socket_id Socket identifier.
    197  *  @param[in] flags    Various receive flags.
    198  *  @param[out] addrlen The source address length.
    199  *  @returns            The number of bytes received.
    200  *  @returns            ENOTSOCK if the socket is not found.
    201  *  @returns            NO_DATA if there are no received packets or data.
    202  *  @returns            ENOMEM if there is not enough memory left.
    203  *  @returns            EINVAL if the received address is not an IP address.
    204  *  @returns            Other error codes as defined for the packet_translate()
    205  *                      function.
    206  *  @returns            Other error codes as defined for the data_reply()
    207  *                      function.
    208  */
    209 int
    210 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    211     size_t * addrlen);
    212 
    213 /*@}*/
    214 
    215 /** UDP global data.
    216  */
     92/** UDP global data.  */
    21793udp_globals_t udp_globals;
    21894
     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 */
    219102int udp_initialize(async_client_conn_t client_connection)
    220103{
    221         ERROR_DECLARE;
    222 
    223104        measured_string_t names[] = {
    224105                {
    225                         str_dup("UDP_CHECKSUM_COMPUTING"),
     106                        (char *) "UDP_CHECKSUM_COMPUTING",
    226107                        22
    227108                },
    228109                {
    229                         str_dup("UDP_AUTOBINDING"),
     110                        (char *) "UDP_AUTOBINDING",
    230111                        15
    231112                }
    232113        };
    233         measured_string_ref configuration;
     114        measured_string_t *configuration;
    234115        size_t count = sizeof(names) / sizeof(measured_string_t);
    235         char * data;
     116        char *data;
     117        int rc;
    236118
    237119        fibril_rwlock_initialize(&udp_globals.lock);
     
    240122        udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    241123            ICMP_CONNECT_TIMEOUT);
     124       
    242125        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
    243126            SERVICE_UDP, client_connection);
    244         if (udp_globals.ip_phone < 0)
     127        if (udp_globals.ip_phone < 0) {
     128                fibril_rwlock_write_unlock(&udp_globals.lock);
    245129                return udp_globals.ip_phone;
    246 
    247         // read default packet dimensions
    248         ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1,
    249             &udp_globals.packet_dimension));
    250         ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets));
    251         if (ERROR_OCCURRED(packet_dimensions_initialize(
    252             &udp_globals.dimensions))) {
     130        }
     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) {
    253148                socket_ports_destroy(&udp_globals.sockets);
    254                 return ERROR_CODE;
    255         }
     149                fibril_rwlock_write_unlock(&udp_globals.lock);
     150                return rc;
     151        }
     152       
    256153        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
    257154        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    258155        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    259156
    260         // get configuration
    261157        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    262158        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
     159
     160        /* Get configuration */
    263161        configuration = &names[0];
    264         ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration,
    265             count, &data));
     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       
    266170        if (configuration) {
    267171                if (configuration[0].value)
     
    280184}
    281185
    282 int
    283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
     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));
     195        return result;
     196}
     197
     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,
    284220    services_t error)
    285221{
    286         int result;
    287 
    288         fibril_rwlock_write_lock(&udp_globals.lock);
    289         result = udp_process_packet(device_id, packet, error);
    290         if (result != EOK)
    291                 fibril_rwlock_write_unlock(&udp_globals.lock);
    292 
    293         return result;
    294 }
    295 
    296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
    297 {
    298         ERROR_DECLARE;
    299 
    300222        size_t length;
    301223        size_t offset;
    302224        int result;
    303         udp_header_ref header;
    304         socket_core_ref socket;
    305         packet_t next_packet;
     225        udp_header_t *header;
     226        socket_core_t *socket;
     227        packet_t *next_packet;
    306228        size_t total_length;
    307229        uint32_t checksum;
    308230        int fragments;
    309         packet_t tmp_packet;
     231        packet_t *tmp_packet;
    310232        icmp_type_t type;
    311233        icmp_code_t code;
     
    313235        struct sockaddr *src;
    314236        struct sockaddr *dest;
    315         packet_dimension_ref packet_dimension;
    316 
    317         if (error) {
    318                 switch (error) {
    319                 case SERVICE_ICMP:
    320                         // ignore error
    321                         // length = icmp_client_header_length(packet);
    322                         // process error
    323                         result = icmp_client_process_packet(packet, &type,
    324                             &code, NULL, NULL);
    325                         if (result < 0)
    326                                 return udp_release_and_return(packet, result);
    327                         length = (size_t) result;
    328                         if (ERROR_OCCURRED(packet_trim(packet, length, 0)))
    329                                 return udp_release_and_return(packet,
    330                                     ERROR_CODE);
    331                         break;
    332                 default:
    333                         return udp_release_and_return(packet, ENOTSUP);
    334                 }
    335         }
    336 
    337         // TODO process received ipopts?
     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? */
    338262        result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
    339263        if (result < 0)
     
    347271                return udp_release_and_return(packet, NO_DATA);
    348272
    349         // trim all but UDP header
    350         if (ERROR_OCCURRED(packet_trim(packet, offset, 0)))
    351                 return udp_release_and_return(packet, ERROR_CODE);
    352 
    353         // get udp header
    354         header = (udp_header_ref) packet_get_data(packet);
     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);
    355280        if (!header)
    356281                return udp_release_and_return(packet, NO_DATA);
    357282
    358         // find the destination socket
     283        /* Find the destination socket */
    359284        socket = socket_port_find(&udp_globals.sockets,
    360285        ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     
    368293        }
    369294
    370         // count the received packet fragments
     295        /* Count the received packet fragments */
    371296        next_packet = packet;
    372297        fragments = 0;
    373298        total_length = ntohs(header->total_length);
    374299
    375         // compute header checksum if set
    376         if (header->checksum && (!error)) {
     300        /* Compute header checksum if set */
     301        if (header->checksum && !error) {
    377302                result = packet_get_addr(packet, (uint8_t **) &src,
    378303                    (uint8_t **) &dest);
    379                 if( result <= 0)
     304                if (result <= 0)
    380305                        return udp_release_and_return(packet, result);
    381 
    382                 if (ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP,
    383                     src, result, dest, result, total_length, &ip_header,
    384                     &length))) {
    385                         return udp_release_and_return(packet, ERROR_CODE);
     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);
    386311                } else {
    387312                        checksum = compute_checksum(0, ip_header, length);
    388                         // the udp header checksum will be added with the first
    389                         // fragment later
     313                        /*
     314                         * The udp header checksum will be added with the first
     315                         * fragment later.
     316                         */
    390317                        free(ip_header);
    391318                }
     
    396323
    397324        do {
    398                 ++ fragments;
     325                fragments++;
    399326                length = packet_get_data_length(next_packet);
    400327                if (length <= 0)
     
    402329
    403330                if (total_length < length) {
    404                         if (ERROR_OCCURRED(packet_trim(next_packet, 0,
    405                             length - total_length))) {
    406                                 return udp_release_and_return(packet,
    407                                     ERROR_CODE);
    408                         }
    409 
    410                         // add partial checksum if set
     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 */
    411336                        if (header->checksum) {
    412337                                checksum = compute_checksum(checksum,
     
    415340                        }
    416341
    417                         // relese the rest of the packet fragments
     342                        /* Relese the rest of the packet fragments */
    418343                        tmp_packet = pq_next(next_packet);
    419344                        while (tmp_packet) {
     
    424349                        }
    425350
    426                         // exit the loop
     351                        /* Exit the loop */
    427352                        break;
    428353                }
    429354                total_length -= length;
    430355
    431                 // add partial checksum if set
     356                /* Add partial checksum if set */
    432357                if (header->checksum) {
    433358                        checksum = compute_checksum(checksum,
     
    438363        } while ((next_packet = pq_next(next_packet)) && (total_length > 0));
    439364
    440         // check checksum
     365        /* Verify checksum */
    441366        if (header->checksum) {
    442367                if (flip_checksum(compact_checksum(checksum)) !=
     
    444369                        if (tl_prepare_icmp_packet(udp_globals.net_phone,
    445370                            udp_globals.icmp_phone, packet, error) == EOK) {
    446                                 // checksum error ICMP
     371                                /* Checksum error ICMP */
    447372                                icmp_parameter_problem_msg(
    448373                                    udp_globals.icmp_phone, ICMP_PARAM_POINTER,
     
    454379        }
    455380
    456         // queue the received packet
    457         if (ERROR_OCCURRED(dyn_fifo_push(&socket->received,
    458             packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE)) ||
    459             ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone,
    460             &udp_globals.dimensions, device_id, &packet_dimension))) {
    461                 return udp_release_and_return(packet, ERROR_CODE);
    462         }
    463 
    464         // 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 */
    465393        fibril_rwlock_write_unlock(&udp_globals.lock);
    466394        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
     
    471399}
    472400
    473 int
    474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
    475     ipc_call_t * answer, int * answer_count)
     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)
    476417{
    477         ERROR_DECLARE;
    478 
    479         packet_t packet;
    480 
    481         *answer_count = 0;
    482 
    483         switch (IPC_GET_METHOD(*call)) {
    484         case NET_TL_RECEIVED:
    485                 if (!ERROR_OCCURRED(packet_translate_remote(
    486                     udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))) {
    487                         ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call),
    488                             packet, SERVICE_UDP, IPC_GET_ERROR(call));
     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;
     426}
     427
     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;
     463        int index;
     464        size_t total_length;
     465        int result;
     466        uint16_t dest_port;
     467        uint32_t checksum;
     468        void *ip_header;
     469        size_t headerlen;
     470        device_id_t device_id;
     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;
     477
     478        socket = socket_cores_find(local_sockets, socket_id);
     479        if (!socket)
     480                return ENOTSOCK;
     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;
     510                packet_dimension = &udp_globals.packet_dimension;
     511//      }
     512
     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)
     517                return result;
     518
     519        total_length = (size_t) result;
     520        if (udp_globals.checksum_computing)
     521                checksum = compute_checksum(0, packet_get_data(packet),
     522                    packet_get_data_length(packet));
     523        else
     524                checksum = 0;
     525
     526        /* Prefix the UDP header */
     527        header = PACKET_PREFIX(packet, udp_header_t);
     528        if (!header)
     529                return udp_release_and_return(packet, ENOMEM);
     530
     531        bzero(header, sizeof(*header));
     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)
     538                        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));
    489549                }
    490                 return ERROR_CODE;
     550        }
     551
     552        /* Set the UDP header */
     553        header->source_port = htons((socket->port > 0) ? socket->port : 0);
     554        header->destination_port = htons(dest_port);
     555        header->total_length = htons(total_length + sizeof(*header));
     556        header->checksum = 0;
     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) {
     563                        free(ip_header);
     564                        return udp_release_and_return(packet, rc);
     565                }
     566
     567                /* Finish the checksum computation */
     568                checksum = compute_checksum(checksum, ip_header, headerlen);
     569                checksum = compute_checksum(checksum, (uint8_t *) header,
     570                    sizeof(*header));
     571                header->checksum =
     572                    htons(flip_checksum(compact_checksum(checksum)));
     573                free(ip_header);
     574        } else {
     575                device_id = DEVICE_INVALID_ID;
     576        }
     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. */
     584        fibril_rwlock_write_unlock(&udp_globals.lock);
     585
     586        /* Send the packet */
     587        ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
     588
     589        return EOK;
     590}
     591
     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;
     615        int packet_id;
     616        packet_t *packet;
     617        udp_header_t *header;
     618        struct sockaddr *addr;
     619        size_t length;
     620        uint8_t *data;
     621        int result;
     622        int rc;
     623
     624        /* Find the socket */
     625        socket = socket_cores_find(local_sockets, socket_id);
     626        if (!socket)
     627                return ENOTSOCK;
     628
     629        /* Get the next received packet */
     630        packet_id = dyn_fifo_value(&socket->received);
     631        if (packet_id < 0)
     632                return NO_DATA;
    491633       
    492         case IPC_M_CONNECT_TO_ME:
    493                 return udp_process_client_messages(callid, * call);
    494         }
    495 
    496         return ENOTSUP;
     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 */
     641        data = packet_get_data(packet);
     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 */
     649        result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
     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);
     654        }
     655        *addrlen = (size_t) result;
     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);
    497692}
    498693
    499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     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)
    500705{
    501706        int res;
     
    509714        ipc_call_t answer;
    510715        int answer_count;
    511         packet_dimension_ref packet_dimension;
     716        packet_dimension_t *packet_dimension;
    512717
    513718        /*
     
    518723        answer_count = 0;
    519724
    520         // The client connection is only in one fibril and therefore no
    521         // additional locks are needed.
     725        /*
     726         * The client connection is only in one fibril and therefore no
     727         * additional locks are needed.
     728         */
    522729
    523730        socket_cores_initialize(&local_sockets);
     
    525732        while (keep_on_going) {
    526733
    527                 // answer the call
     734                /* Answer the call */
    528735                answer_call(callid, res, &answer, answer_count);
    529736
    530                 // refresh data
     737                /* Refresh data */
    531738                refresh_answer(&answer, &answer_count);
    532739
    533                 // get the next call
     740                /* Get the next call */
    534741                callid = async_get_call(&call);
    535742
    536                 // process the call
     743                /* Process the call */
    537744                switch (IPC_GET_METHOD(call)) {
    538745                case IPC_M_PHONE_HUNGUP:
     
    628835        }
    629836
    630         // release the application phone
     837        /* Release the application phone */
    631838        ipc_hangup(app_phone);
    632839
    633         // release all local sockets
     840        /* Release all local sockets */
    634841        socket_cores_release(udp_globals.net_phone, &local_sockets,
    635842            &udp_globals.sockets, NULL);
     
    638845}
    639846
    640 int
    641 udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    642     const struct sockaddr *addr, socklen_t addrlen, int fragments,
    643     size_t *data_fragment_size, int flags)
     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)
    644862{
    645         ERROR_DECLARE;
    646 
    647         socket_core_ref socket;
    648         packet_t packet;
    649         packet_t next_packet;
    650         udp_header_ref header;
    651         int index;
    652         size_t total_length;
    653         int result;
    654         uint16_t dest_port;
    655         uint32_t checksum;
    656         void *ip_header;
    657         size_t headerlen;
    658         device_id_t device_id;
    659         packet_dimension_ref packet_dimension;
    660 
    661         ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port));
    662 
    663         socket = socket_cores_find(local_sockets, socket_id);
    664         if (!socket)
    665                 return ENOTSOCK;
    666 
    667         if ((socket->port <= 0) && udp_globals.autobinding) {
    668                 // bind the socket to a random free port if not bound
    669 //              do {
    670                         // try to find a free port
    671 //                      fibril_rwlock_read_unlock(&udp_globals.lock);
    672 //                      fibril_rwlock_write_lock(&udp_globals.lock);
    673                         // might be changed in the meantime
    674 //                      if (socket->port <= 0) {
    675                                 if (ERROR_OCCURRED(socket_bind_free_port(
    676                                     &udp_globals.sockets, socket,
    677                                     UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
    678                                     udp_globals.last_used_port))) {
    679 //                                      fibril_rwlock_write_unlock(
    680 //                                          &udp_globals.lock);
    681 //                                      fibril_rwlock_read_lock(
    682 //                                          &udp_globals.lock);
    683                                         return ERROR_CODE;
    684                                 }
    685                                 // set the next port as the search starting port
    686                                 // number
    687                                 udp_globals.last_used_port = socket->port;
    688 //                      }
    689 //                      fibril_rwlock_write_unlock(&udp_globals.lock);
    690 //                      fibril_rwlock_read_lock(&udp_globals.lock);
    691                         // might be changed in the meantime
    692 //              } while (socket->port <= 0);
    693         }
    694 
    695         if (udp_globals.checksum_computing) {
    696                 if (ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone,
    697                     IPPROTO_UDP, addr, addrlen, &device_id, &ip_header,
    698                     &headerlen))) {
    699                         return udp_release_and_return(packet, ERROR_CODE);
    700                 }
    701                 // get the device packet dimension
    702 //              ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone,
    703 //                  &udp_globals.dimensions, device_id, &packet_dimension));
    704         }
    705 //      } else {
    706                 // do not ask all the time
    707                 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1,
    708                     &udp_globals.packet_dimension));
    709                 packet_dimension = &udp_globals.packet_dimension;
    710 //      }
    711 
    712         // read the first packet fragment
    713         result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
    714             UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
    715         if (result < 0)
    716                 return result;
    717 
    718         total_length = (size_t) result;
    719         if (udp_globals.checksum_computing)
    720                 checksum = compute_checksum(0, packet_get_data(packet),
    721                     packet_get_data_length(packet));
    722         else
    723                 checksum = 0;
    724 
    725         // prefix the udp header
    726         header = PACKET_PREFIX(packet, udp_header_t);
    727         if(! header)
    728                 return udp_release_and_return(packet, ENOMEM);
    729 
    730         bzero(header, sizeof(*header));
    731         // read the rest of the packet fragments
    732         for (index = 1; index < fragments; ++ index) {
    733                 result = tl_socket_read_packet_data(udp_globals.net_phone,
    734                     &next_packet, 0, packet_dimension, addr, addrlen);
    735                 if (result < 0)
    736                         return udp_release_and_return(packet, result);
    737 
    738                 if (ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0)))
    739                         return udp_release_and_return(packet, ERROR_CODE);
    740 
    741                 total_length += (size_t) result;
    742                 if (udp_globals.checksum_computing) {
    743                         checksum = compute_checksum(checksum,
    744                             packet_get_data(next_packet),
    745                             packet_get_data_length(next_packet));
    746                 }
    747         }
    748 
    749         // set the udp header
    750         header->source_port = htons((socket->port > 0) ? socket->port : 0);
    751         header->destination_port = htons(dest_port);
    752         header->total_length = htons(total_length + sizeof(*header));
    753         header->checksum = 0;
    754         if (udp_globals.checksum_computing) {
    755                 // update the pseudo header
    756                 if (ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(
    757                     ip_header, headerlen, total_length + UDP_HEADER_SIZE))) {
    758                         free(ip_header);
    759                         return udp_release_and_return(packet, ERROR_CODE);
    760                 }
    761 
    762                 // finish the checksum computation
    763                 checksum = compute_checksum(checksum, ip_header, headerlen);
    764                 checksum = compute_checksum(checksum, (uint8_t *) header,
    765                     sizeof(*header));
    766                 header->checksum =
    767                     htons(flip_checksum(compact_checksum(checksum)));
    768                 free(ip_header);
    769         } else {
    770                 device_id = DEVICE_INVALID_ID;
    771         }
    772 
    773         // prepare the first packet fragment
    774         if (ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0,
    775             0, 0))) {
    776                 return udp_release_and_return(packet, ERROR_CODE);
    777         }
    778 
    779         // send the packet
    780         fibril_rwlock_write_unlock(&udp_globals.lock);
    781         ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
    782 
    783         return EOK;
     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;
    784881}
    785882
    786 int
    787 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    788     size_t *addrlen)
    789 {
    790         ERROR_DECLARE;
    791 
    792         socket_core_ref socket;
    793         int packet_id;
    794         packet_t packet;
    795         udp_header_ref header;
    796         struct sockaddr *addr;
    797         size_t length;
    798         uint8_t *data;
    799         int result;
    800 
    801         // find the socket
    802         socket = socket_cores_find(local_sockets, socket_id);
    803         if (!socket)
    804                 return ENOTSOCK;
    805 
    806         // get the next received packet
    807         packet_id = dyn_fifo_value(&socket->received);
    808         if (packet_id < 0)
    809                 return NO_DATA;
    810 
    811         ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet,
    812             packet_id));
    813 
    814         // get udp header
    815         data = packet_get_data(packet);
    816         if (!data) {
    817                 pq_release_remote(udp_globals.net_phone, packet_id);
    818                 return NO_DATA;
    819         }
    820         header = (udp_header_ref) data;
    821 
    822         // set the source address port
    823         result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
    824         if (ERROR_OCCURRED(tl_set_address_port(addr, result,
    825             ntohs(header->source_port)))) {
    826                 pq_release_remote(udp_globals.net_phone, packet_id);
    827                 return ERROR_CODE;
    828         }
    829         *addrlen = (size_t) result;
    830 
    831         // send the source address
    832         ERROR_PROPAGATE(data_reply(addr, * addrlen));
    833 
    834         // trim the header
    835         ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));
    836 
    837         // reply the packets
    838         ERROR_PROPAGATE(socket_reply_packets(packet, &length));
    839 
    840         // release the packet
    841         dyn_fifo_pop(&socket->received);
    842         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    843 
    844         // return the total length
    845         return (int) length;
    846 }
    847 
    848 int udp_release_and_return(packet_t packet, int result)
    849 {
    850         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    851         return result;
    852 }
    853 
    854883/** Default thread for new connections.
    855884 *
    856  *  @param[in] iid      The initial message identifier.
    857  *  @param[in] icall    The initial message call structure.
    858  *
     885 * @param[in] iid       The initial message identifier.
     886 * @param[in] icall     The initial message call structure.
    859887 */
    860888static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     
    882910               
    883911                /*
    884                  * End if said to either by the message or the processing result
     912                 * End if told to either by the message or the processing
     913                 * result.
    885914                 */
    886915                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    895924/** Starts the module.
    896925 *
    897  *  @param argc         The count of the command line arguments. Ignored
    898  *                      parameter.
    899  *  @param argv         The command line parameters. Ignored parameter.
    900  *
    901  *  @returns            EOK on success.
    902  *  @returns            Other error codes as defined for each specific module
     926 * @return              EOK on success.
     927 * @return              Other error codes as defined for each specific module
    903928 *                      start function.
    904929 */
    905930int main(int argc, char *argv[])
    906931{
    907         ERROR_DECLARE;
     932        int rc;
    908933       
    909934        /* Start the module */
    910         if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
    911                 return ERROR_CODE;
    912        
    913         return EOK;
     935        rc = tl_module_start_standalone(tl_client_connection);
     936        return rc;
    914937}
    915938
Note: See TracChangeset for help on using the changeset viewer.