Ignore:
File:
1 edited

Legend:

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

    r46d4d9f r8e3a65c  
    2828
    2929/** @addtogroup udp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * UDP module implementation.
    35  * @see udp.h
    36  */
    37 
    38 #include "udp.h"
    39 #include "udp_header.h"
    40 #include "udp_module.h"
     34 *  UDP module implementation.
     35 *  @see udp.h
     36 */
    4137
    4238#include <async.h>
     
    4945#include <ipc/tl.h>
    5046#include <ipc/socket.h>
    51 #include <adt/dynamic_fifo.h>
    5247#include <errno.h>
     48#include <err.h>
    5349
    5450#include <net/socket_codes.h>
     
    5955#include <net/modules.h>
    6056
     57#include <adt/dynamic_fifo.h>
    6158#include <packet_client.h>
    6259#include <packet_remote.h>
     
    7269#include <tl_interface.h>
    7370
     71#include "udp.h"
     72#include "udp_header.h"
     73#include "udp_module.h"
     74
    7475/** UDP module name. */
    7576#define NAME    "UDP protocol"
     
    9091#define UDP_FREE_PORTS_END              65535
    9192
    92 /** UDP global data.  */
     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 */
     107int
     108udp_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 */
     132int
     133udp_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 */
     141int 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 */
     156int 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 */
     185int
     186udp_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 */
     209int
     210udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
     211    size_t * addrlen);
     212
     213/*@}*/
     214
     215/** UDP global data.
     216 */
    93217udp_globals_t udp_globals;
    94218
    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  */
    102219int udp_initialize(async_client_conn_t client_connection)
    103220{
     221        ERROR_DECLARE;
     222
    104223        measured_string_t names[] = {
    105224                {
    106                         (char *) "UDP_CHECKSUM_COMPUTING",
     225                        str_dup("UDP_CHECKSUM_COMPUTING"),
    107226                        22
    108227                },
    109228                {
    110                         (char *) "UDP_AUTOBINDING",
     229                        str_dup("UDP_AUTOBINDING"),
    111230                        15
    112231                }
    113232        };
    114         measured_string_t *configuration;
     233        measured_string_ref configuration;
    115234        size_t count = sizeof(names) / sizeof(measured_string_t);
    116         char *data;
    117         int rc;
     235        char * data;
    118236
    119237        fibril_rwlock_initialize(&udp_globals.lock);
     
    122240        udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    123241            ICMP_CONNECT_TIMEOUT);
    124        
    125242        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
    126243            SERVICE_UDP, client_connection);
    127         if (udp_globals.ip_phone < 0) {
    128                 fibril_rwlock_write_unlock(&udp_globals.lock);
     244        if (udp_globals.ip_phone < 0)
    129245                return udp_globals.ip_phone;
    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) {
     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))) {
    148253                socket_ports_destroy(&udp_globals.sockets);
    149                 fibril_rwlock_write_unlock(&udp_globals.lock);
    150                 return rc;
    151         }
    152        
     254                return ERROR_CODE;
     255        }
    153256        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
    154257        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    155258        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    156259
     260        // get configuration
    157261        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    158262        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
    159 
    160         /* Get configuration */
    161263        configuration = &names[0];
    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        
     264        ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration,
     265            count, &data));
    170266        if (configuration) {
    171267                if (configuration[0].value)
     
    184280}
    185281
    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  */
    192 static int udp_release_and_return(packet_t *packet, int result)
     282int
     283udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
     284    services_t error)
    193285{
    194         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     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
    195293        return result;
    196294}
    197295
    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  */
    219 static int udp_process_packet(device_id_t device_id, packet_t *packet,
    220     services_t error)
     296int udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
    221297{
     298        ERROR_DECLARE;
     299
    222300        size_t length;
    223301        size_t offset;
    224302        int result;
    225         udp_header_t *header;
    226         socket_core_t *socket;
    227         packet_t *next_packet;
     303        udp_header_ref header;
     304        socket_core_ref socket;
     305        packet_t next_packet;
    228306        size_t total_length;
    229307        uint32_t checksum;
    230308        int fragments;
    231         packet_t *tmp_packet;
     309        packet_t tmp_packet;
    232310        icmp_type_t type;
    233311        icmp_code_t code;
     
    235313        struct sockaddr *src;
    236314        struct sockaddr *dest;
    237         packet_dimension_t *packet_dimension;
    238         int rc;
    239 
    240         switch (error) {
    241         case SERVICE_NONE:
    242                 break;
    243         case SERVICE_ICMP:
    244                 /* Ignore error */
    245                 // length = icmp_client_header_length(packet);
    246 
    247                 /* Process error */
    248                 result = icmp_client_process_packet(packet, &type,
    249                     &code, NULL, NULL);
    250                 if (result < 0)
    251                         return udp_release_and_return(packet, result);
    252                 length = (size_t) result;
    253                 rc = packet_trim(packet, length, 0);
    254                 if (rc != EOK)
    255                         return udp_release_and_return(packet, rc);
    256                 break;
    257         default:
    258                 return udp_release_and_return(packet, ENOTSUP);
    259         }
    260 
    261         /* TODO process received ipopts? */
     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?
    262338        result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
    263339        if (result < 0)
     
    271347                return udp_release_and_return(packet, NO_DATA);
    272348
    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);
     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);
    280355        if (!header)
    281356                return udp_release_and_return(packet, NO_DATA);
    282357
    283         /* Find the destination socket */
     358        // find the destination socket
    284359        socket = socket_port_find(&udp_globals.sockets,
    285360        ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     
    293368        }
    294369
    295         /* Count the received packet fragments */
     370        // count the received packet fragments
    296371        next_packet = packet;
    297372        fragments = 0;
    298373        total_length = ntohs(header->total_length);
    299374
    300         /* Compute header checksum if set */
    301         if (header->checksum && !error) {
     375        // compute header checksum if set
     376        if (header->checksum && (!error)) {
    302377                result = packet_get_addr(packet, (uint8_t **) &src,
    303378                    (uint8_t **) &dest);
    304                 if (result <= 0)
     379                if( result <= 0)
    305380                        return udp_release_and_return(packet, result);
    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);
     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);
    311386                } else {
    312387                        checksum = compute_checksum(0, ip_header, length);
    313                         /*
    314                          * The udp header checksum will be added with the first
    315                          * fragment later.
    316                          */
     388                        // the udp header checksum will be added with the first
     389                        // fragment later
    317390                        free(ip_header);
    318391                }
     
    323396
    324397        do {
    325                 fragments++;
     398                ++ fragments;
    326399                length = packet_get_data_length(next_packet);
    327400                if (length <= 0)
     
    329402
    330403                if (total_length < length) {
    331                         rc = packet_trim(next_packet, 0, length - total_length);
    332                         if (rc != EOK)
    333                                 return udp_release_and_return(packet, rc);
    334 
    335                         /* Add partial checksum if set */
     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
    336411                        if (header->checksum) {
    337412                                checksum = compute_checksum(checksum,
     
    340415                        }
    341416
    342                         /* Relese the rest of the packet fragments */
     417                        // relese the rest of the packet fragments
    343418                        tmp_packet = pq_next(next_packet);
    344419                        while (tmp_packet) {
     
    349424                        }
    350425
    351                         /* Exit the loop */
     426                        // exit the loop
    352427                        break;
    353428                }
    354429                total_length -= length;
    355430
    356                 /* Add partial checksum if set */
     431                // add partial checksum if set
    357432                if (header->checksum) {
    358433                        checksum = compute_checksum(checksum,
     
    363438        } while ((next_packet = pq_next(next_packet)) && (total_length > 0));
    364439
    365         /* Verify checksum */
     440        // check checksum
    366441        if (header->checksum) {
    367442                if (flip_checksum(compact_checksum(checksum)) !=
     
    369444                        if (tl_prepare_icmp_packet(udp_globals.net_phone,
    370445                            udp_globals.icmp_phone, packet, error) == EOK) {
    371                                 /* Checksum error ICMP */
     446                                // checksum error ICMP
    372447                                icmp_parameter_problem_msg(
    373448                                    udp_globals.icmp_phone, ICMP_PARAM_POINTER,
     
    379454        }
    380455
    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 */
     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
    393465        fibril_rwlock_write_unlock(&udp_globals.lock);
    394466        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
     
    399471}
    400472
    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  */
    415 static int udp_received_msg(device_id_t device_id, packet_t *packet,
    416     services_t receiver, services_t error)
     473int
     474udp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
     475    ipc_call_t * answer, int * answer_count)
    417476{
    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;
     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));
     489                }
     490                return ERROR_CODE;
     491       
     492        case IPC_M_CONNECT_TO_ME:
     493                return udp_process_client_messages(callid, * call);
     494        }
     495
     496        return ENOTSUP;
    426497}
    427498
    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  */
    455 static 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));
    549                 }
    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  */
    611 static 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;
    633        
    634         rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id);
    635         if (rc != EOK) {
    636                 (void) dyn_fifo_pop(&socket->received);
    637                 return rc;
    638         }
    639 
    640         /* Get UDP header */
    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);
    692 }
    693 
    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  */
    704 static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     499int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    705500{
    706501        int res;
     
    714509        ipc_call_t answer;
    715510        int answer_count;
    716         packet_dimension_t *packet_dimension;
     511        packet_dimension_ref packet_dimension;
    717512
    718513        /*
     
    723518        answer_count = 0;
    724519
    725         /*
    726          * The client connection is only in one fibril and therefore no
    727          * additional locks are needed.
    728          */
     520        // The client connection is only in one fibril and therefore no
     521        // additional locks are needed.
    729522
    730523        socket_cores_initialize(&local_sockets);
     
    732525        while (keep_on_going) {
    733526
    734                 /* Answer the call */
     527                // answer the call
    735528                answer_call(callid, res, &answer, answer_count);
    736529
    737                 /* Refresh data */
     530                // refresh data
    738531                refresh_answer(&answer, &answer_count);
    739532
    740                 /* Get the next call */
     533                // get the next call
    741534                callid = async_get_call(&call);
    742535
    743                 /* Process the call */
     536                // process the call
    744537                switch (IPC_GET_METHOD(call)) {
    745538                case IPC_M_PHONE_HUNGUP:
     
    835628        }
    836629
    837         /* Release the application phone */
     630        // release the application phone
    838631        ipc_hangup(app_phone);
    839632
    840         /* Release all local sockets */
     633        // release all local sockets
    841634        socket_cores_release(udp_globals.net_phone, &local_sockets,
    842635            &udp_globals.sockets, NULL);
     
    845638}
    846639
    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  */
    860 int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    861     ipc_call_t *answer, int *answer_count)
     640int
     641udp_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)
    862644{
    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;
     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;
    881784}
    882785
     786int
     787udp_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
     848int 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
    883854/** Default thread for new connections.
    884855 *
    885  * @param[in] iid       The initial message identifier.
    886  * @param[in] icall     The initial message call structure.
     856 *  @param[in] iid      The initial message identifier.
     857 *  @param[in] icall    The initial message call structure.
     858 *
    887859 */
    888860static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     
    910882               
    911883                /*
    912                  * End if told to either by the message or the processing
    913                  * result.
     884                 * End if said to either by the message or the processing result
    914885                 */
    915886                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    924895/** Starts the module.
    925896 *
    926  * @return              EOK on success.
    927  * @return              Other error codes as defined for each specific module
     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
    928903 *                      start function.
    929904 */
    930905int main(int argc, char *argv[])
    931906{
    932         int rc;
     907        ERROR_DECLARE;
    933908       
    934909        /* Start the module */
    935         rc = tl_module_start_standalone(tl_client_connection);
    936         return rc;
     910        if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
     911                return ERROR_CODE;
     912       
     913        return EOK;
    937914}
    938915
Note: See TracChangeset for help on using the changeset viewer.