Ignore:
File:
1 edited

Legend:

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

    r08042bd 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  * @returns             EOK on success.
    100  * @returns             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                }
     
    114233        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         }
    131246
    132247        // 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) {
     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  * @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  */
    219 static int
    220 udp_process_packet(device_id_t device_id, packet_t packet, 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;
     
    236314        struct sockaddr *dest;
    237315        packet_dimension_ref 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                 // 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);
     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                }
    258335        }
    259336
     
    271348
    272349        // trim all but UDP header
    273         rc = packet_trim(packet, offset, 0);
    274         if (rc != EOK)
    275                 return udp_release_and_return(packet, rc);
     350        if (ERROR_OCCURRED(packet_trim(packet, offset, 0)))
     351                return udp_release_and_return(packet, ERROR_CODE);
    276352
    277353        // get udp header
     
    298374
    299375        // compute header checksum if set
    300         if (header->checksum && !error) {
     376        if (header->checksum && (!error)) {
    301377                result = packet_get_addr(packet, (uint8_t **) &src,
    302378                    (uint8_t **) &dest);
    303                 if (result <= 0)
     379                if( result <= 0)
    304380                        return udp_release_and_return(packet, result);
    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);
     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);
    310386                } else {
    311387                        checksum = compute_checksum(0, ip_header, length);
     
    320396
    321397        do {
    322                 fragments++;
     398                ++ fragments;
    323399                length = packet_get_data_length(next_packet);
    324400                if (length <= 0)
     
    326402
    327403                if (total_length < length) {
    328                         rc = packet_trim(next_packet, 0, length - total_length);
    329                         if (rc != EOK)
    330                                 return udp_release_and_return(packet, rc);
     404                        if (ERROR_OCCURRED(packet_trim(next_packet, 0,
     405                            length - total_length))) {
     406                                return udp_release_and_return(packet,
     407                                    ERROR_CODE);
     408                        }
    331409
    332410                        // add partial checksum if set
     
    377455
    378456        // queue the received packet
    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);
     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        }
    388463
    389464        // notify the destination socket
     
    396471}
    397472
    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  */
    412 static int
    413 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
    414     services_t error)
     473int
     474udp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
     475    ipc_call_t * answer, int * answer_count)
    415476{
    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;
     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;
    424497}
    425498
    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  */
    453 static int
     499int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     500{
     501        int res;
     502        bool keep_on_going = true;
     503        socket_cores_t local_sockets;
     504        int app_phone = IPC_GET_PHONE(&call);
     505        struct sockaddr *addr;
     506        int socket_id;
     507        size_t addrlen;
     508        size_t size;
     509        ipc_call_t answer;
     510        int answer_count;
     511        packet_dimension_ref packet_dimension;
     512
     513        /*
     514         * Accept the connection
     515         *  - Answer the first IPC_M_CONNECT_TO_ME call.
     516         */
     517        res = EOK;
     518        answer_count = 0;
     519
     520        // The client connection is only in one fibril and therefore no
     521        // additional locks are needed.
     522
     523        socket_cores_initialize(&local_sockets);
     524
     525        while (keep_on_going) {
     526
     527                // answer the call
     528                answer_call(callid, res, &answer, answer_count);
     529
     530                // refresh data
     531                refresh_answer(&answer, &answer_count);
     532
     533                // get the next call
     534                callid = async_get_call(&call);
     535
     536                // process the call
     537                switch (IPC_GET_METHOD(call)) {
     538                case IPC_M_PHONE_HUNGUP:
     539                        keep_on_going = false;
     540                        res = EHANGUP;
     541                        break;
     542
     543                case NET_SOCKET:
     544                        socket_id = SOCKET_GET_SOCKET_ID(call);
     545                        res = socket_create(&local_sockets, app_phone, NULL,
     546                            &socket_id);
     547                        SOCKET_SET_SOCKET_ID(answer, socket_id);
     548
     549                        if (res != EOK)
     550                                break;
     551                       
     552                        if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
     553                            &udp_globals.dimensions, DEVICE_INVALID_ID,
     554                            &packet_dimension) == EOK) {
     555                                SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     556                                    packet_dimension->content);
     557                        }
     558
     559//                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     560//                          MAX_UDP_FRAGMENT_SIZE);
     561                        SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
     562                        answer_count = 3;
     563                        break;
     564
     565                case NET_SOCKET_BIND:
     566                        res = data_receive((void **) &addr, &addrlen);
     567                        if (res != EOK)
     568                                break;
     569                        fibril_rwlock_write_lock(&udp_globals.lock);
     570                        res = socket_bind(&local_sockets, &udp_globals.sockets,
     571                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     572                            UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
     573                            udp_globals.last_used_port);
     574                        fibril_rwlock_write_unlock(&udp_globals.lock);
     575                        free(addr);
     576                        break;
     577
     578                case NET_SOCKET_SENDTO:
     579                        res = data_receive((void **) &addr, &addrlen);
     580                        if (res != EOK)
     581                                break;
     582
     583                        fibril_rwlock_write_lock(&udp_globals.lock);
     584                        res = udp_sendto_message(&local_sockets,
     585                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     586                            SOCKET_GET_DATA_FRAGMENTS(call), &size,
     587                            SOCKET_GET_FLAGS(call));
     588                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     589
     590                        if (res != EOK)
     591                                fibril_rwlock_write_unlock(&udp_globals.lock);
     592                        else
     593                                answer_count = 2;
     594                       
     595                        free(addr);
     596                        break;
     597
     598                case NET_SOCKET_RECVFROM:
     599                        fibril_rwlock_write_lock(&udp_globals.lock);
     600                        res = udp_recvfrom_message(&local_sockets,
     601                             SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
     602                             &addrlen);
     603                        fibril_rwlock_write_unlock(&udp_globals.lock);
     604
     605                        if (res <= 0)
     606                                break;
     607
     608                        SOCKET_SET_READ_DATA_LENGTH(answer, res);
     609                        SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
     610                        answer_count = 3;
     611                        res = EOK;
     612                        break;
     613                       
     614                case NET_SOCKET_CLOSE:
     615                        fibril_rwlock_write_lock(&udp_globals.lock);
     616                        res = socket_destroy(udp_globals.net_phone,
     617                            SOCKET_GET_SOCKET_ID(call), &local_sockets,
     618                            &udp_globals.sockets, NULL);
     619                        fibril_rwlock_write_unlock(&udp_globals.lock);
     620                        break;
     621
     622                case NET_SOCKET_GETSOCKOPT:
     623                case NET_SOCKET_SETSOCKOPT:
     624                default:
     625                        res = ENOTSUP;
     626                        break;
     627                }
     628        }
     629
     630        // release the application phone
     631        ipc_hangup(app_phone);
     632
     633        // release all local sockets
     634        socket_cores_release(udp_globals.net_phone, &local_sockets,
     635            &udp_globals.sockets, NULL);
     636
     637        return res;
     638}
     639
     640int
    454641udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    455642    const struct sockaddr *addr, socklen_t addrlen, int fragments,
    456643    size_t *data_fragment_size, int flags)
    457644{
     645        ERROR_DECLARE;
     646
    458647        socket_core_ref socket;
    459648        packet_t packet;
     
    469658        device_id_t device_id;
    470659        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;
     660
     661        ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port));
    476662
    477663        socket = socket_cores_find(local_sockets, socket_id);
     
    481667        if ((socket->port <= 0) && udp_globals.autobinding) {
    482668                // 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;
     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);
    490693        }
    491694
    492695        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;
     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                }
    497701                // 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;
     702//              ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone,
     703//                  &udp_globals.dimensions, device_id, &packet_dimension));
    502704        }
    503705//      } else {
    504706                // 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;
     707                ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1,
     708                    &udp_globals.packet_dimension));
    509709                packet_dimension = &udp_globals.packet_dimension;
    510710//      }
     
    525725        // prefix the udp header
    526726        header = PACKET_PREFIX(packet, udp_header_t);
    527         if (!header)
     727        if(! header)
    528728                return udp_release_and_return(packet, ENOMEM);
    529729
    530730        bzero(header, sizeof(*header));
    531731        // read the rest of the packet fragments
    532         for (index = 1; index < fragments; index++) {
     732        for (index = 1; index < fragments; ++ index) {
    533733                result = tl_socket_read_packet_data(udp_globals.net_phone,
    534734                    &next_packet, 0, packet_dimension, addr, addrlen);
     
    536736                        return udp_release_and_return(packet, result);
    537737
    538                 rc = pq_add(&packet, next_packet, index, 0);
    539                 if (rc != EOK)
    540                         return udp_release_and_return(packet, rc);
     738                if (ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0)))
     739                        return udp_release_and_return(packet, ERROR_CODE);
    541740
    542741                total_length += (size_t) result;
     
    555754        if (udp_globals.checksum_computing) {
    556755                // 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) {
     756                if (ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(
     757                    ip_header, headerlen, total_length + UDP_HEADER_SIZE))) {
    560758                        free(ip_header);
    561                         return udp_release_and_return(packet, rc);
     759                        return udp_release_and_return(packet, ERROR_CODE);
    562760                }
    563761
     
    574772
    575773        // 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. */
     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
    581780        fibril_rwlock_write_unlock(&udp_globals.lock);
    582 
    583         // send the packet
    584781        ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
    585782
     
    587784}
    588785
    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  */
    608 static int
     786int
    609787udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    610788    size_t *addrlen)
    611789{
     790        ERROR_DECLARE;
     791
    612792        socket_core_ref socket;
    613793        int packet_id;
     
    618798        uint8_t *data;
    619799        int result;
    620         int rc;
    621800
    622801        // find the socket
     
    629808        if (packet_id < 0)
    630809                return NO_DATA;
    631        
    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         }
     810
     811        ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet,
     812            packet_id));
    637813
    638814        // get udp header
    639815        data = packet_get_data(packet);
    640816        if (!data) {
    641                 (void) dyn_fifo_pop(&socket->received);
    642                 return udp_release_and_return(packet, NO_DATA);
     817                pq_release_remote(udp_globals.net_phone, packet_id);
     818                return NO_DATA;
    643819        }
    644820        header = (udp_header_ref) data;
     
    646822        // set the source address port
    647823        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);
     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;
    652828        }
    653829        *addrlen = (size_t) result;
    654830
    655831        // 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         }
     832        ERROR_PROPAGATE(data_reply(addr, * addrlen));
    666833
    667834        // 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         }
     835        ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));
    673836
    674837        // 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);
     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;
    690846}
    691847
    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  */
    702 static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     848int udp_release_and_return(packet_t packet, int result)
    703849{
    704         int res;
    705         bool keep_on_going = true;
    706         socket_cores_t local_sockets;
    707         int app_phone = IPC_GET_PHONE(&call);
    708         struct sockaddr *addr;
    709         int socket_id;
    710         size_t addrlen;
    711         size_t size;
    712         ipc_call_t answer;
    713         int answer_count;
    714         packet_dimension_ref packet_dimension;
    715 
    716         /*
    717          * Accept the connection
    718          *  - Answer the first IPC_M_CONNECT_TO_ME call.
    719          */
    720         res = EOK;
    721         answer_count = 0;
    722 
    723         // The client connection is only in one fibril and therefore no
    724         // additional locks are needed.
    725 
    726         socket_cores_initialize(&local_sockets);
    727 
    728         while (keep_on_going) {
    729 
    730                 // answer the call
    731                 answer_call(callid, res, &answer, answer_count);
    732 
    733                 // refresh data
    734                 refresh_answer(&answer, &answer_count);
    735 
    736                 // get the next call
    737                 callid = async_get_call(&call);
    738 
    739                 // process the call
    740                 switch (IPC_GET_METHOD(call)) {
    741                 case IPC_M_PHONE_HUNGUP:
    742                         keep_on_going = false;
    743                         res = EHANGUP;
    744                         break;
    745 
    746                 case NET_SOCKET:
    747                         socket_id = SOCKET_GET_SOCKET_ID(call);
    748                         res = socket_create(&local_sockets, app_phone, NULL,
    749                             &socket_id);
    750                         SOCKET_SET_SOCKET_ID(answer, socket_id);
    751 
    752                         if (res != EOK)
    753                                 break;
    754                        
    755                         if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
    756                             &udp_globals.dimensions, DEVICE_INVALID_ID,
    757                             &packet_dimension) == EOK) {
    758                                 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    759                                     packet_dimension->content);
    760                         }
    761 
    762 //                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    763 //                          MAX_UDP_FRAGMENT_SIZE);
    764                         SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
    765                         answer_count = 3;
    766                         break;
    767 
    768                 case NET_SOCKET_BIND:
    769                         res = data_receive((void **) &addr, &addrlen);
    770                         if (res != EOK)
    771                                 break;
    772                         fibril_rwlock_write_lock(&udp_globals.lock);
    773                         res = socket_bind(&local_sockets, &udp_globals.sockets,
    774                             SOCKET_GET_SOCKET_ID(call), addr, addrlen,
    775                             UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
    776                             udp_globals.last_used_port);
    777                         fibril_rwlock_write_unlock(&udp_globals.lock);
    778                         free(addr);
    779                         break;
    780 
    781                 case NET_SOCKET_SENDTO:
    782                         res = data_receive((void **) &addr, &addrlen);
    783                         if (res != EOK)
    784                                 break;
    785 
    786                         fibril_rwlock_write_lock(&udp_globals.lock);
    787                         res = udp_sendto_message(&local_sockets,
    788                             SOCKET_GET_SOCKET_ID(call), addr, addrlen,
    789                             SOCKET_GET_DATA_FRAGMENTS(call), &size,
    790                             SOCKET_GET_FLAGS(call));
    791                         SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
    792 
    793                         if (res != EOK)
    794                                 fibril_rwlock_write_unlock(&udp_globals.lock);
    795                         else
    796                                 answer_count = 2;
    797                        
    798                         free(addr);
    799                         break;
    800 
    801                 case NET_SOCKET_RECVFROM:
    802                         fibril_rwlock_write_lock(&udp_globals.lock);
    803                         res = udp_recvfrom_message(&local_sockets,
    804                              SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
    805                              &addrlen);
    806                         fibril_rwlock_write_unlock(&udp_globals.lock);
    807 
    808                         if (res <= 0)
    809                                 break;
    810 
    811                         SOCKET_SET_READ_DATA_LENGTH(answer, res);
    812                         SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
    813                         answer_count = 3;
    814                         res = EOK;
    815                         break;
    816                        
    817                 case NET_SOCKET_CLOSE:
    818                         fibril_rwlock_write_lock(&udp_globals.lock);
    819                         res = socket_destroy(udp_globals.net_phone,
    820                             SOCKET_GET_SOCKET_ID(call), &local_sockets,
    821                             &udp_globals.sockets, NULL);
    822                         fibril_rwlock_write_unlock(&udp_globals.lock);
    823                         break;
    824 
    825                 case NET_SOCKET_GETSOCKOPT:
    826                 case NET_SOCKET_SETSOCKOPT:
    827                 default:
    828                         res = ENOTSUP;
    829                         break;
    830                 }
    831         }
    832 
    833         // release the application phone
    834         ipc_hangup(app_phone);
    835 
    836         // release all local sockets
    837         socket_cores_release(udp_globals.net_phone, &local_sockets,
    838             &udp_globals.sockets, NULL);
    839 
    840         return res;
     850        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     851        return result;
    841852}
    842853
    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  */
    856 int
    857 udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    858     ipc_call_t *answer, int *answer_count)
    859 {
    860         packet_t packet;
    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;
    878 }
    879 
    880854/** Default thread for new connections.
    881855 *
    882  * @param[in] iid       The initial message identifier.
    883  * @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 *
    884859 */
    885860static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     
    907882               
    908883                /*
    909                  * End if told to either by the message or the processing
    910                  * result.
     884                 * End if said to either by the message or the processing result
    911885                 */
    912886                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    921895/** Starts the module.
    922896 *
    923  * @returns             EOK on success.
    924  * @returns             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
    925903 *                      start function.
    926904 */
    927905int main(int argc, char *argv[])
    928906{
    929         int rc;
     907        ERROR_DECLARE;
    930908       
    931909        /* Start the module */
    932         rc = tl_module_start_standalone(tl_client_connection);
    933         return rc;
     910        if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
     911                return ERROR_CODE;
     912       
     913        return EOK;
    934914}
    935915
Note: See TracChangeset for help on using the changeset viewer.