Ignore:
File:
1 edited

Legend:

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

    r8e3a65c r08042bd  
    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 * @returns             EOK on success.
     100 * @returns             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                }
     
    233114        measured_string_ref 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;
     130        }
    246131
    247132        // 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))) {
     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,
    284     services_t error)
     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)
    285193{
    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 
     194        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    293195        return result;
    294196}
    295197
    296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
     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 * @returns             EOK on success.
     208 * @returns             EINVAL if the packet is not valid.
     209 * @returns             EINVAL if the stored packet address is not the
     210 *                      an_addr_t.
     211 * @returns             EINVAL if the packet does not contain any data.
     212 * @returns             NO_DATA if the packet content is shorter than the user
     213 *                      datagram header.
     214 * @returns             ENOMEM if there is not enough memory left.
     215 * @returns             EADDRNOTAVAIL if the destination socket does not exist.
     216 * @returns             Other error codes as defined for the
     217 *                      ip_client_process_packet() function.
     218 */
     219static int
     220udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
    297221{
    298         ERROR_DECLARE;
    299 
    300222        size_t length;
    301223        size_t offset;
     
    314236        struct sockaddr *dest;
    315237        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                 }
     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                // process error
     247                result = icmp_client_process_packet(packet, &type,
     248                    &code, NULL, NULL);
     249                if (result < 0)
     250                        return udp_release_and_return(packet, result);
     251                length = (size_t) result;
     252                rc = packet_trim(packet, length, 0);
     253                if (rc != EOK)
     254                        return udp_release_and_return(packet, rc);
     255                break;
     256        default:
     257                return udp_release_and_return(packet, ENOTSUP);
    335258        }
    336259
     
    348271
    349272        // trim all but UDP header
    350         if (ERROR_OCCURRED(packet_trim(packet, offset, 0)))
    351                 return udp_release_and_return(packet, ERROR_CODE);
     273        rc = packet_trim(packet, offset, 0);
     274        if (rc != EOK)
     275                return udp_release_and_return(packet, rc);
    352276
    353277        // get udp header
     
    374298
    375299        // compute header checksum if set
    376         if (header->checksum && (!error)) {
     300        if (header->checksum && !error) {
    377301                result = packet_get_addr(packet, (uint8_t **) &src,
    378302                    (uint8_t **) &dest);
    379                 if( result <= 0)
     303                if (result <= 0)
    380304                        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);
     305               
     306                rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest,
     307                    result, total_length, &ip_header, &length);
     308                if (rc != EOK) {
     309                        return udp_release_and_return(packet, rc);
    386310                } else {
    387311                        checksum = compute_checksum(0, ip_header, length);
     
    396320
    397321        do {
    398                 ++ fragments;
     322                fragments++;
    399323                length = packet_get_data_length(next_packet);
    400324                if (length <= 0)
     
    402326
    403327                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                         }
     328                        rc = packet_trim(next_packet, 0, length - total_length);
     329                        if (rc != EOK)
     330                                return udp_release_and_return(packet, rc);
    409331
    410332                        // add partial checksum if set
     
    455377
    456378        // 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         }
     379        rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
     380            SOCKET_MAX_RECEIVED_SIZE);
     381        if (rc != EOK)
     382                return udp_release_and_return(packet, rc);
     383               
     384        rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
     385            &udp_globals.dimensions, device_id, &packet_dimension);
     386        if (rc != EOK)
     387                return udp_release_and_return(packet, rc);
    463388
    464389        // notify the destination socket
     
    471396}
    472397
    473 int
    474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
    475     ipc_call_t * answer, int * answer_count)
     398/** Processes the received UDP packet queue.
     399 *
     400 * Is used as an entry point from the underlying IP module.
     401 * Locks the global lock and calls udp_process_packet() function.
     402 *
     403 * @param[in] device_id The receiving device identifier.
     404 * @param[in,out] packet The received packet queue.
     405 * @param receiver      The target service. Ignored parameter.
     406 * @param[in] error     The packet error reporting service. Prefixes the
     407 *                      received packet.
     408 * @returns             EOK on success.
     409 * @returns             Other error codes as defined for the
     410 *                      udp_process_packet() function.
     411 */
     412static int
     413udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
     414    services_t error)
    476415{
    477         ERROR_DECLARE;
    478 
     416        int result;
     417
     418        fibril_rwlock_write_lock(&udp_globals.lock);
     419        result = udp_process_packet(device_id, packet, error);
     420        if (result != EOK)
     421                fibril_rwlock_write_unlock(&udp_globals.lock);
     422
     423        return result;
     424}
     425
     426/** Sends data from the socket to the remote address.
     427 *
     428 * Binds the socket to a free port if not already connected/bound.
     429 * Handles the NET_SOCKET_SENDTO message.
     430 * Supports AF_INET and AF_INET6 address families.
     431 *
     432 * @param[in,out] local_sockets The application local sockets.
     433 * @param[in] socket_id Socket identifier.
     434 * @param[in] addr      The destination address.
     435 * @param[in] addrlen   The address length.
     436 * @param[in] fragments The number of data fragments.
     437 * @param[out] data_fragment_size The data fragment size in bytes.
     438 * @param[in] flags     Various send flags.
     439 * @returns             EOK on success.
     440 * @returns             EAFNOTSUPPORT if the address family is not supported.
     441 * @returns             ENOTSOCK if the socket is not found.
     442 * @returns             EINVAL if the address is invalid.
     443 * @returns             ENOTCONN if the sending socket is not and cannot be
     444 *                      bound.
     445 * @returns             ENOMEM if there is not enough memory left.
     446 * @returns             Other error codes as defined for the
     447 *                      socket_read_packet_data() function.
     448 * @returns             Other error codes as defined for the
     449 *                      ip_client_prepare_packet() function.
     450 * @returns             Other error codes as defined for the ip_send_msg()
     451 *                      function.
     452 */
     453static int
     454udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
     455    const struct sockaddr *addr, socklen_t addrlen, int fragments,
     456    size_t *data_fragment_size, int flags)
     457{
     458        socket_core_ref socket;
    479459        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));
     460        packet_t next_packet;
     461        udp_header_ref header;
     462        int index;
     463        size_t total_length;
     464        int result;
     465        uint16_t dest_port;
     466        uint32_t checksum;
     467        void *ip_header;
     468        size_t headerlen;
     469        device_id_t device_id;
     470        packet_dimension_ref packet_dimension;
     471        int rc;
     472       
     473        rc = tl_get_address_port(addr, addrlen, &dest_port);
     474        if (rc != EOK)
     475                return rc;
     476
     477        socket = socket_cores_find(local_sockets, socket_id);
     478        if (!socket)
     479                return ENOTSOCK;
     480
     481        if ((socket->port <= 0) && udp_globals.autobinding) {
     482                // bind the socket to a random free port if not bound
     483                rc = socket_bind_free_port(&udp_globals.sockets, socket,
     484                    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
     485                    udp_globals.last_used_port);
     486                if (rc != EOK)
     487                        return rc;
     488                // set the next port as the search starting port number
     489                udp_globals.last_used_port = socket->port;
     490        }
     491
     492        if (udp_globals.checksum_computing) {
     493                rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr,
     494                    addrlen, &device_id, &ip_header, &headerlen);
     495                if (rc != EOK)
     496                        return rc;
     497                // get the device packet dimension
     498//              rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
     499//                  &udp_globals.dimensions, device_id, &packet_dimension);
     500//              if (rc != EOK)
     501//                      return rc;
     502        }
     503//      } else {
     504                // do not ask all the time
     505                rc = ip_packet_size_req(udp_globals.ip_phone, -1,
     506                    &udp_globals.packet_dimension);
     507                if (rc != EOK)
     508                        return rc;
     509                packet_dimension = &udp_globals.packet_dimension;
     510//      }
     511
     512        // read the first packet fragment
     513        result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
     514            UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
     515        if (result < 0)
     516                return result;
     517
     518        total_length = (size_t) result;
     519        if (udp_globals.checksum_computing)
     520                checksum = compute_checksum(0, packet_get_data(packet),
     521                    packet_get_data_length(packet));
     522        else
     523                checksum = 0;
     524
     525        // prefix the udp header
     526        header = PACKET_PREFIX(packet, udp_header_t);
     527        if (!header)
     528                return udp_release_and_return(packet, ENOMEM);
     529
     530        bzero(header, sizeof(*header));
     531        // read the rest of the packet fragments
     532        for (index = 1; index < fragments; index++) {
     533                result = tl_socket_read_packet_data(udp_globals.net_phone,
     534                    &next_packet, 0, packet_dimension, addr, addrlen);
     535                if (result < 0)
     536                        return udp_release_and_return(packet, result);
     537
     538                rc = pq_add(&packet, next_packet, index, 0);
     539                if (rc != EOK)
     540                        return udp_release_and_return(packet, rc);
     541
     542                total_length += (size_t) result;
     543                if (udp_globals.checksum_computing) {
     544                        checksum = compute_checksum(checksum,
     545                            packet_get_data(next_packet),
     546                            packet_get_data_length(next_packet));
    489547                }
    490                 return ERROR_CODE;
     548        }
     549
     550        // set the udp header
     551        header->source_port = htons((socket->port > 0) ? socket->port : 0);
     552        header->destination_port = htons(dest_port);
     553        header->total_length = htons(total_length + sizeof(*header));
     554        header->checksum = 0;
     555        if (udp_globals.checksum_computing) {
     556                // update the pseudo header
     557                rc = ip_client_set_pseudo_header_data_length(ip_header,
     558                    headerlen, total_length + UDP_HEADER_SIZE);
     559                if (rc != EOK) {
     560                        free(ip_header);
     561                        return udp_release_and_return(packet, rc);
     562                }
     563
     564                // finish the checksum computation
     565                checksum = compute_checksum(checksum, ip_header, headerlen);
     566                checksum = compute_checksum(checksum, (uint8_t *) header,
     567                    sizeof(*header));
     568                header->checksum =
     569                    htons(flip_checksum(compact_checksum(checksum)));
     570                free(ip_header);
     571        } else {
     572                device_id = DEVICE_INVALID_ID;
     573        }
     574
     575        // prepare the first packet fragment
     576        rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0);
     577        if (rc != EOK)
     578                return udp_release_and_return(packet, rc);
     579
     580        /* Release the UDP global lock on success. */
     581        fibril_rwlock_write_unlock(&udp_globals.lock);
     582
     583        // send the packet
     584        ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
     585
     586        return EOK;
     587}
     588
     589/** Receives data to the socket.
     590 *
     591 * Handles the NET_SOCKET_RECVFROM message.
     592 * Replies the source address as well.
     593 *
     594 * @param[in] local_sockets The application local sockets.
     595 * @param[in] socket_id Socket identifier.
     596 * @param[in] flags     Various receive flags.
     597 * @param[out] addrlen  The source address length.
     598 * @returns             The number of bytes received.
     599 * @returns             ENOTSOCK if the socket is not found.
     600 * @returns             NO_DATA if there are no received packets or data.
     601 * @returns             ENOMEM if there is not enough memory left.
     602 * @returns             EINVAL if the received address is not an IP address.
     603 * @returns             Other error codes as defined for the packet_translate()
     604 *                      function.
     605 * @returns             Other error codes as defined for the data_reply()
     606 *                      function.
     607 */
     608static int
     609udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
     610    size_t *addrlen)
     611{
     612        socket_core_ref socket;
     613        int packet_id;
     614        packet_t packet;
     615        udp_header_ref header;
     616        struct sockaddr *addr;
     617        size_t length;
     618        uint8_t *data;
     619        int result;
     620        int rc;
     621
     622        // find the socket
     623        socket = socket_cores_find(local_sockets, socket_id);
     624        if (!socket)
     625                return ENOTSOCK;
     626
     627        // get the next received packet
     628        packet_id = dyn_fifo_value(&socket->received);
     629        if (packet_id < 0)
     630                return NO_DATA;
    491631       
    492         case IPC_M_CONNECT_TO_ME:
    493                 return udp_process_client_messages(callid, * call);
    494         }
    495 
    496         return ENOTSUP;
     632        rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id);
     633        if (rc != EOK) {
     634                (void) dyn_fifo_pop(&socket->received);
     635                return rc;
     636        }
     637
     638        // get udp header
     639        data = packet_get_data(packet);
     640        if (!data) {
     641                (void) dyn_fifo_pop(&socket->received);
     642                return udp_release_and_return(packet, NO_DATA);
     643        }
     644        header = (udp_header_ref) data;
     645
     646        // set the source address port
     647        result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
     648        rc = tl_set_address_port(addr, result, ntohs(header->source_port));
     649        if (rc != EOK) {
     650                (void) dyn_fifo_pop(&socket->received);
     651                return udp_release_and_return(packet, rc);
     652        }
     653        *addrlen = (size_t) result;
     654
     655        // send the source address
     656        rc = data_reply(addr, *addrlen);
     657        switch (rc) {
     658        case EOK:
     659                break;
     660        case EOVERFLOW:
     661                return rc;
     662        default:
     663                (void) dyn_fifo_pop(&socket->received);
     664                return udp_release_and_return(packet, rc);
     665        }
     666
     667        // trim the header
     668        rc = packet_trim(packet, UDP_HEADER_SIZE, 0);
     669        if (rc != EOK) {
     670                (void) dyn_fifo_pop(&socket->received);
     671                return udp_release_and_return(packet, rc);
     672        }
     673
     674        // reply the packets
     675        rc = socket_reply_packets(packet, &length);
     676        switch (rc) {
     677        case EOK:
     678                break;
     679        case EOVERFLOW:
     680                return rc;
     681        default:
     682                (void) dyn_fifo_pop(&socket->received);
     683                return udp_release_and_return(packet, rc);
     684        }
     685
     686        (void) dyn_fifo_pop(&socket->received);
     687
     688        // release the packet and return the total length
     689        return udp_release_and_return(packet, (int) length);
    497690}
    498691
    499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     692/** Processes the socket client messages.
     693 *
     694 * Runs until the client module disconnects.
     695 *
     696 * @param[in] callid    The message identifier.
     697 * @param[in] call      The message parameters.
     698 * @returns             EOK on success.
     699 *
     700 * @see socket.h
     701 */
     702static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    500703{
    501704        int res;
     
    638841}
    639842
     843/** Processes the UDP message.
     844 *
     845 * @param[in] callid    The message identifier.
     846 * @param[in] call      The message parameters.
     847 * @param[out] answer   The message answer parameters.
     848 * @param[out] answer_count The last parameter for the actual answer in the
     849 *                      answer parameter.
     850 * @returns             EOK on success.
     851 * @returns             ENOTSUP if the message is not known.
     852 *
     853 * @see udp_interface.h
     854 * @see IS_NET_UDP_MESSAGE()
     855 */
    640856int
    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)
     857udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     858    ipc_call_t *answer, int *answer_count)
    644859{
    645         ERROR_DECLARE;
    646 
    647         socket_core_ref socket;
    648860        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;
     861        int rc;
     862
     863        *answer_count = 0;
     864
     865        switch (IPC_GET_METHOD(*call)) {
     866        case NET_TL_RECEIVED:
     867                rc = packet_translate_remote(udp_globals.net_phone, &packet,
     868                    IPC_GET_PACKET(call));
     869                if (rc != EOK)
     870                        return rc;
     871                return udp_received_msg(IPC_GET_DEVICE(call), packet,
     872                    SERVICE_UDP, IPC_GET_ERROR(call));
     873        case IPC_M_CONNECT_TO_ME:
     874                return udp_process_client_messages(callid, * call);
     875        }
     876
     877        return ENOTSUP;
    784878}
    785879
    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 
    854880/** Default thread for new connections.
    855881 *
    856  *  @param[in] iid      The initial message identifier.
    857  *  @param[in] icall    The initial message call structure.
    858  *
     882 * @param[in] iid       The initial message identifier.
     883 * @param[in] icall     The initial message call structure.
    859884 */
    860885static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     
    882907               
    883908                /*
    884                  * End if said to either by the message or the processing result
     909                 * End if told to either by the message or the processing
     910                 * result.
    885911                 */
    886912                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    895921/** Starts the module.
    896922 *
    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
     923 * @returns             EOK on success.
     924 * @returns             Other error codes as defined for each specific module
    903925 *                      start function.
    904926 */
    905927int main(int argc, char *argv[])
    906928{
    907         ERROR_DECLARE;
     929        int rc;
    908930       
    909931        /* Start the module */
    910         if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
    911                 return ERROR_CODE;
    912        
    913         return EOK;
     932        rc = tl_module_start_standalone(tl_client_connection);
     933        return rc;
    914934}
    915935
Note: See TracChangeset for help on using the changeset viewer.