Ignore:
File:
1 edited

Legend:

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

    r3f8c1f7 r14f1db0  
    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>
     
    4642#include <ipc/ipc.h>
    4743#include <ipc/services.h>
    48 #include <ipc/net.h>
    49 #include <ipc/tl.h>
    50 #include <ipc/socket.h>
     44
     45#include <net_err.h>
     46#include <net_messages.h>
     47#include <net_modules.h>
    5148#include <adt/dynamic_fifo.h>
    52 #include <errno.h>
    53 
    54 #include <net/socket_codes.h>
    55 #include <net/ip_protocols.h>
    56 #include <net/in.h>
    57 #include <net/in6.h>
    58 #include <net/inet.h>
    59 #include <net/modules.h>
    60 
    61 #include <packet_client.h>
     49#include <packet/packet_client.h>
    6250#include <packet_remote.h>
    6351#include <net_checksum.h>
     52#include <in.h>
     53#include <in6.h>
     54#include <inet.h>
    6455#include <ip_client.h>
    6556#include <ip_interface.h>
     57#include <ip_protocols.h>
    6658#include <icmp_client.h>
    6759#include <icmp_interface.h>
    6860#include <net_interface.h>
     61#include <socket_codes.h>
     62#include <socket_errno.h>
    6963#include <socket_core.h>
     64#include <socket_messages.h>
    7065#include <tl_common.h>
    7166#include <tl_local.h>
    7267#include <tl_interface.h>
    73 
    74 /** UDP module name. */
     68#include <tl_messages.h>
     69
     70#include "udp.h"
     71#include "udp_header.h"
     72#include "udp_module.h"
     73
     74/** UDP module name.
     75 */
    7576#define NAME    "UDP protocol"
    7677
    77 /** Default UDP checksum computing. */
     78/** Default UDP checksum computing.
     79 */
    7880#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING      true
    7981
    80 /** Default UDP autobind when sending via unbound sockets. */
     82/** Default UDP autobind when sending via unbound sockets.
     83 */
    8184#define NET_DEFAULT_UDP_AUTOBINDING     true
    8285
    83 /** Maximum UDP fragment size. */
    84 #define MAX_UDP_FRAGMENT_SIZE           65535
    85 
    86 /** Free ports pool start. */
    87 #define UDP_FREE_PORTS_START            1025
    88 
    89 /** Free ports pool end. */
     86/** Maximum UDP fragment size.
     87 */
     88#define MAX_UDP_FRAGMENT_SIZE   65535
     89
     90/** Free ports pool start.
     91 */
     92#define UDP_FREE_PORTS_START    1025
     93
     94/** Free ports pool end.
     95 */
    9096#define UDP_FREE_PORTS_END              65535
    9197
    92 /** UDP global data.  */
    93 udp_globals_t udp_globals;
    94 
    95 /** Initializes the UDP module.
    96  *
    97  * @param[in] client_connection The client connection processing function. The
    98  *                      module skeleton propagates its own one.
    99  * @return              EOK on success.
    100  * @return              ENOMEM if there is not enough memory left.
    101  */
    102 int udp_initialize(async_client_conn_t client_connection)
    103 {
    104         measured_string_t names[] = {
    105                 {
    106                         (char *) "UDP_CHECKSUM_COMPUTING",
    107                         22
    108                 },
    109                 {
    110                         (char *) "UDP_AUTOBINDING",
    111                         15
    112                 }
    113         };
    114         measured_string_t *configuration;
     98/** Processes the received UDP packet queue.
     99 *  Is used as an entry point from the underlying IP module.
     100 *  Locks the global lock and calls udp_process_packet() function.
     101 *  @param[in] device_id The receiving device identifier.
     102 *  @param[in,out] packet The received packet queue.
     103 *  @param receiver The target service. Ignored parameter.
     104 *  @param[in] error The packet error reporting service. Prefixes the received packet.
     105 *  @returns EOK on success.
     106 *  @returns Other error codes as defined for the udp_process_packet() function.
     107 */
     108int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
     109
     110/** Processes the received UDP packet queue.
     111 *  Notifies the destination socket application.
     112 *  Releases the packet on error or sends an ICMP error notification..
     113 *  @param[in] device_id The receiving device identifier.
     114 *  @param[in,out] packet The received packet queue.
     115 *  @param[in] error The packet error reporting service. Prefixes the received packet.
     116 *  @returns EOK on success.
     117 *  @returns EINVAL if the packet is not valid.
     118 *  @returns EINVAL if the stored packet address is not the an_addr_t.
     119 *  @returns EINVAL if the packet does not contain any data.
     120 *  @returns NO_DATA if the packet content is shorter than the user datagram header.
     121 *  @returns ENOMEM if there is not enough memory left.
     122 *  @returns EADDRNOTAVAIL if the destination socket does not exist.
     123 *  @returns Other error codes as defined for the ip_client_process_packet() function.
     124 */
     125int udp_process_packet(device_id_t device_id, packet_t packet, services_t error);
     126
     127/** Releases the packet and returns the result.
     128 *  @param[in] packet The packet queue to be released.
     129 *  @param[in] result The result to be returned.
     130 *  @return The result parameter.
     131 */
     132int udp_release_and_return(packet_t packet, int result);
     133
     134/** @name Socket messages processing functions
     135 */
     136/*@{*/
     137
     138/** Processes the socket client messages.
     139 *  Runs until the client module disconnects.
     140 *  @param[in] callid The message identifier.
     141 *  @param[in] call The message parameters.
     142 *  @returns EOK on success.
     143 *  @see socket.h
     144 */
     145int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
     146
     147/** Sends data from the socket to the remote address.
     148 *  Binds the socket to a free port if not already connected/bound.
     149 *  Handles the NET_SOCKET_SENDTO message.
     150 *  Supports AF_INET and AF_INET6 address families.
     151 *  @param[in,out] local_sockets The application local sockets.
     152 *  @param[in] socket_id Socket identifier.
     153 *  @param[in] addr The destination address.
     154 *  @param[in] addrlen The address length.
     155 *  @param[in] fragments The number of data fragments.
     156 *  @param[out] data_fragment_size The data fragment size in bytes.
     157 *  @param[in] flags Various send flags.
     158 *  @returns EOK on success.
     159 *  @returns EAFNOTSUPPORT if the address family is not supported.
     160 *  @returns ENOTSOCK if the socket is not found.
     161 *  @returns EINVAL if the address is invalid.
     162 *  @returns ENOTCONN if the sending socket is not and cannot be bound.
     163 *  @returns ENOMEM if there is not enough memory left.
     164 *  @returns Other error codes as defined for the socket_read_packet_data() function.
     165 *  @returns Other error codes as defined for the ip_client_prepare_packet() function.
     166 *  @returns Other error codes as defined for the ip_send_msg() function.
     167 */
     168int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags);
     169
     170/** Receives data to the socket.
     171 *  Handles the NET_SOCKET_RECVFROM message.
     172 *  Replies the source address as well.
     173 *  @param[in] local_sockets The application local sockets.
     174 *  @param[in] socket_id Socket identifier.
     175 *  @param[in] flags Various receive flags.
     176 *  @param[out] addrlen The source address length.
     177 *  @returns The number of bytes received.
     178 *  @returns ENOTSOCK if the socket is not found.
     179 *  @returns NO_DATA if there are no received packets or data.
     180 *  @returns ENOMEM if there is not enough memory left.
     181 *  @returns EINVAL if the received address is not an IP address.
     182 *  @returns Other error codes as defined for the packet_translate() function.
     183 *  @returns Other error codes as defined for the data_reply() function.
     184 */
     185int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen);
     186
     187/*@}*/
     188
     189/** UDP global data.
     190 */
     191udp_globals_t   udp_globals;
     192
     193int udp_initialize(async_client_conn_t client_connection){
     194        ERROR_DECLARE;
     195
     196        measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}};
     197        measured_string_ref configuration;
    115198        size_t count = sizeof(names) / sizeof(measured_string_t);
    116         char *data;
    117         int rc;
     199        char * data;
    118200
    119201        fibril_rwlock_initialize(&udp_globals.lock);
    120202        fibril_rwlock_write_lock(&udp_globals.lock);
    121 
    122         udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    123             ICMP_CONNECT_TIMEOUT);
    124        
    125         udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
    126             SERVICE_UDP, client_connection);
    127         if (udp_globals.ip_phone < 0) {
    128                 fibril_rwlock_write_unlock(&udp_globals.lock);
     203        udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
     204        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg);
     205        if(udp_globals.ip_phone < 0){
    129206                return udp_globals.ip_phone;
    130207        }
    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) {
     208        // read default packet dimensions
     209        ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
     210        ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets));
     211        if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){
    148212                socket_ports_destroy(&udp_globals.sockets);
    149                 fibril_rwlock_write_unlock(&udp_globals.lock);
    150                 return rc;
    151         }
    152        
     213                return ERROR_CODE;
     214        }
    153215        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
    154216        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    155217        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    156 
     218        // get configuration
    157219        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    158220        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
    159 
    160         /* Get configuration */
    161221        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        
    170         if (configuration) {
    171                 if (configuration[0].value)
    172                         udp_globals.checksum_computing =
    173                             (configuration[0].value[0] == 'y');
    174                
    175                 if (configuration[1].value)
    176                         udp_globals.autobinding =
    177                             (configuration[1].value[0] == 'y');
    178 
     222        ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, count, &data));
     223        if(configuration){
     224                if(configuration[0].value){
     225                        udp_globals.checksum_computing = (configuration[0].value[0] == 'y');
     226                }
     227                if(configuration[1].value){
     228                        udp_globals.autobinding = (configuration[1].value[0] == 'y');
     229                }
    179230                net_free_settings(configuration, data);
    180231        }
    181 
    182232        fibril_rwlock_write_unlock(&udp_globals.lock);
    183233        return EOK;
    184234}
    185235
    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)
    193 {
    194         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     236int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
     237        int result;
     238
     239        fibril_rwlock_write_lock(&udp_globals.lock);
     240        result = udp_process_packet(device_id, packet, error);
     241        if(result != EOK){
     242                fibril_rwlock_write_unlock(&udp_globals.lock);
     243        }
     244
    195245        return result;
    196246}
    197247
    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)
    221 {
     248int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){
     249        ERROR_DECLARE;
     250
    222251        size_t length;
    223252        size_t offset;
    224253        int result;
    225         udp_header_t *header;
    226         socket_core_t *socket;
    227         packet_t *next_packet;
     254        udp_header_ref header;
     255        socket_core_ref socket;
     256        packet_t next_packet;
    228257        size_t total_length;
    229258        uint32_t checksum;
    230259        int fragments;
    231         packet_t *tmp_packet;
     260        packet_t tmp_packet;
    232261        icmp_type_t type;
    233262        icmp_code_t code;
    234263        void *ip_header;
    235         struct sockaddr *src;
    236         struct sockaddr *dest;
    237         packet_dimension_t *packet_dimension;
    238         int rc;
    239 
    240         switch (error) {
    241         case SERVICE_NONE:
    242                 break;
    243         case SERVICE_ICMP:
    244                 /* Ignore error */
    245                 // length = icmp_client_header_length(packet);
    246 
    247                 /* Process error */
    248                 result = icmp_client_process_packet(packet, &type,
    249                     &code, NULL, NULL);
    250                 if (result < 0)
    251                         return udp_release_and_return(packet, result);
    252                 length = (size_t) result;
    253                 rc = packet_trim(packet, length, 0);
    254                 if (rc != EOK)
    255                         return udp_release_and_return(packet, rc);
    256                 break;
    257         default:
    258                 return udp_release_and_return(packet, ENOTSUP);
    259         }
    260 
    261         /* TODO process received ipopts? */
     264        struct sockaddr * src;
     265        struct sockaddr * dest;
     266        packet_dimension_ref packet_dimension;
     267
     268        if(error){
     269                switch(error){
     270                        case SERVICE_ICMP:
     271                                // ignore error
     272                                // length = icmp_client_header_length(packet);
     273                                // process error
     274                                result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     275                                if(result < 0){
     276                                        return udp_release_and_return(packet, result);
     277                                }
     278                                length = (size_t) result;
     279                                if(ERROR_OCCURRED(packet_trim(packet, length, 0))){
     280                                        return udp_release_and_return(packet, ERROR_CODE);
     281                                }
     282                                break;
     283                        default:
     284                                return udp_release_and_return(packet, ENOTSUP);
     285                }
     286        }
     287        // TODO process received ipopts?
    262288        result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
    263         if (result < 0)
     289        if(result < 0){
    264290                return udp_release_and_return(packet, result);
     291        }
    265292        offset = (size_t) result;
    266293
    267294        length = packet_get_data_length(packet);
    268         if (length <= 0)
     295        if(length <= 0){
    269296                return udp_release_and_return(packet, EINVAL);
    270         if (length < UDP_HEADER_SIZE + offset)
     297        }
     298        if(length < UDP_HEADER_SIZE + offset){
    271299                return udp_release_and_return(packet, NO_DATA);
    272 
    273         /* Trim all but UDP header */
    274         rc = packet_trim(packet, offset, 0);
    275         if (rc != EOK)
    276                 return udp_release_and_return(packet, rc);
    277 
    278         /* Get UDP header */
    279         header = (udp_header_t *) packet_get_data(packet);
    280         if (!header)
     300        }
     301
     302        // trim all but UDP header
     303        if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){
     304                return udp_release_and_return(packet, ERROR_CODE);
     305        }
     306
     307        // get udp header
     308        header = (udp_header_ref) packet_get_data(packet);
     309        if(! header){
    281310                return udp_release_and_return(packet, NO_DATA);
    282 
    283         /* Find the destination socket */
    284         socket = socket_port_find(&udp_globals.sockets,
    285         ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
    286         if (!socket) {
    287                 if (tl_prepare_icmp_packet(udp_globals.net_phone,
    288                     udp_globals.icmp_phone, packet, error) == EOK) {
    289                         icmp_destination_unreachable_msg(udp_globals.icmp_phone,
    290                             ICMP_PORT_UNREACH, 0, packet);
     311        }
     312        // find the destination socket
     313        socket = socket_port_find(&udp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     314        if(! socket){
     315                if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
     316                        icmp_destination_unreachable_msg(udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet);
    291317                }
    292318                return EADDRNOTAVAIL;
    293319        }
    294320
    295         /* Count the received packet fragments */
     321        // count the received packet fragments
    296322        next_packet = packet;
    297323        fragments = 0;
    298324        total_length = ntohs(header->total_length);
    299 
    300         /* Compute header checksum if set */
    301         if (header->checksum && !error) {
    302                 result = packet_get_addr(packet, (uint8_t **) &src,
    303                     (uint8_t **) &dest);
    304                 if (result <= 0)
     325        // compute header checksum if set
     326        if(header->checksum && (! error)){
     327                result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     328                if(result <= 0){
    305329                        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);
    311                 } else {
     330                }
     331                if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){
     332                        return udp_release_and_return(packet, ERROR_CODE);
     333                }else{
    312334                        checksum = compute_checksum(0, ip_header, length);
    313                         /*
    314                          * The udp header checksum will be added with the first
    315                          * fragment later.
    316                          */
     335                        // the udp header checksum will be added with the first fragment later
    317336                        free(ip_header);
    318337                }
    319         } else {
     338        }else{
    320339                header->checksum = 0;
    321340                checksum = 0;
    322341        }
    323342
    324         do {
    325                 fragments++;
     343        do{
     344                ++ fragments;
    326345                length = packet_get_data_length(next_packet);
    327                 if (length <= 0)
     346                if(length <= 0){
    328347                        return udp_release_and_return(packet, NO_DATA);
    329 
    330                 if (total_length < length) {
    331                         rc = packet_trim(next_packet, 0, length - total_length);
    332                         if (rc != EOK)
    333                                 return udp_release_and_return(packet, rc);
    334 
    335                         /* Add partial checksum if set */
    336                         if (header->checksum) {
    337                                 checksum = compute_checksum(checksum,
    338                                     packet_get_data(packet),
    339                                     packet_get_data_length(packet));
     348                }
     349                if(total_length < length){
     350                        if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - total_length))){
     351                                return udp_release_and_return(packet, ERROR_CODE);
    340352                        }
    341 
    342                         /* Relese the rest of the packet fragments */
     353                        // add partial checksum if set
     354                        if(header->checksum){
     355                                checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
     356                        }
     357                        // relese the rest of the packet fragments
    343358                        tmp_packet = pq_next(next_packet);
    344                         while (tmp_packet) {
     359                        while(tmp_packet){
    345360                                next_packet = pq_detach(tmp_packet);
    346                                 pq_release_remote(udp_globals.net_phone,
    347                                     packet_get_id(tmp_packet));
     361                                pq_release_remote(udp_globals.net_phone, packet_get_id(tmp_packet));
    348362                                tmp_packet = next_packet;
    349363                        }
    350 
    351                         /* Exit the loop */
     364                        // exit the loop
    352365                        break;
    353366                }
    354367                total_length -= length;
    355 
    356                 /* Add partial checksum if set */
    357                 if (header->checksum) {
    358                         checksum = compute_checksum(checksum,
    359                             packet_get_data(packet),
    360                             packet_get_data_length(packet));
    361                 }
    362 
    363         } while ((next_packet = pq_next(next_packet)) && (total_length > 0));
    364 
    365         /* Verify checksum */
    366         if (header->checksum) {
    367                 if (flip_checksum(compact_checksum(checksum)) !=
    368                     IP_CHECKSUM_ZERO) {
    369                         if (tl_prepare_icmp_packet(udp_globals.net_phone,
    370                             udp_globals.icmp_phone, packet, error) == EOK) {
    371                                 /* Checksum error ICMP */
    372                                 icmp_parameter_problem_msg(
    373                                     udp_globals.icmp_phone, ICMP_PARAM_POINTER,
    374                                     ((size_t) ((void *) &header->checksum)) -
    375                                     ((size_t) ((void *) header)), packet);
     368                // add partial checksum if set
     369                if(header->checksum){
     370                        checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet));
     371                }
     372        }while((next_packet = pq_next(next_packet)) && (total_length > 0));
     373
     374        // check checksum
     375        if(header->checksum){
     376                if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){
     377                        if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){
     378                                // checksum error ICMP
     379                                icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet);
    376380                        }
    377381                        return EINVAL;
     
    379383        }
    380384
    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 */
     385        // queue the received packet
     386        if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE))
     387            || ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension))){
     388                return udp_release_and_return(packet, ERROR_CODE);
     389        }
     390
     391        // notify the destination socket
    393392        fibril_rwlock_write_unlock(&udp_globals.lock);
    394         async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
    395             (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,
    396             (ipcarg_t) fragments);
    397 
     393        async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments);
    398394        return EOK;
    399395}
    400396
    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)
    417 {
    418         int result;
    419 
    420         fibril_rwlock_write_lock(&udp_globals.lock);
    421         result = udp_process_packet(device_id, packet, error);
    422         if (result != EOK)
    423                 fibril_rwlock_write_unlock(&udp_globals.lock);
    424 
    425         return result;
    426 }
    427 
    428 /** Sends data from the socket to the remote address.
    429  *
    430  * Binds the socket to a free port if not already connected/bound.
    431  * Handles the NET_SOCKET_SENDTO message.
    432  * Supports AF_INET and AF_INET6 address families.
    433  *
    434  * @param[in,out] local_sockets The application local sockets.
    435  * @param[in] socket_id Socket identifier.
    436  * @param[in] addr      The destination address.
    437  * @param[in] addrlen   The address length.
    438  * @param[in] fragments The number of data fragments.
    439  * @param[out] data_fragment_size The data fragment size in bytes.
    440  * @param[in] flags     Various send flags.
    441  * @return              EOK on success.
    442  * @return              EAFNOTSUPPORT if the address family is not supported.
    443  * @return              ENOTSOCK if the socket is not found.
    444  * @return              EINVAL if the address is invalid.
    445  * @return              ENOTCONN if the sending socket is not and cannot be
    446  *                      bound.
    447  * @return              ENOMEM if there is not enough memory left.
    448  * @return              Other error codes as defined for the
    449  *                      socket_read_packet_data() function.
    450  * @return              Other error codes as defined for the
    451  *                      ip_client_prepare_packet() function.
    452  * @return              Other error codes as defined for the ip_send_msg()
    453  *                      function.
    454  */
    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;
     397int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     398        ERROR_DECLARE;
     399
     400        packet_t packet;
     401
     402        *answer_count = 0;
     403        switch(IPC_GET_METHOD(*call)){
     404                case NET_TL_RECEIVED:
     405                        if(! ERROR_OCCURRED(packet_translate_remote(udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     406                                ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_UDP, IPC_GET_ERROR(call));
     407                        }
     408                        return ERROR_CODE;
     409                case IPC_M_CONNECT_TO_ME:
     410                        return udp_process_client_messages(callid, * call);
     411        }
     412        return ENOTSUP;
     413}
     414
     415int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
     416        int res;
     417        bool keep_on_going = true;
     418        socket_cores_t local_sockets;
     419        int app_phone = IPC_GET_PHONE(&call);
     420        struct sockaddr * addr;
     421        int socket_id;
     422        size_t addrlen;
     423        size_t size;
     424        ipc_call_t answer;
     425        int answer_count;
     426        packet_dimension_ref packet_dimension;
     427
     428        /*
     429         * Accept the connection
     430         *  - Answer the first IPC_M_CONNECT_TO_ME call.
     431         */
     432        res = EOK;
     433        answer_count = 0;
     434
     435        // The client connection is only in one fibril and therefore no additional locks are needed.
     436
     437        socket_cores_initialize(&local_sockets);
     438
     439        while(keep_on_going){
     440
     441                // answer the call
     442                answer_call(callid, res, &answer, answer_count);
     443
     444                // refresh data
     445                refresh_answer(&answer, &answer_count);
     446
     447                // get the next call
     448                callid = async_get_call(&call);
     449
     450                // process the call
     451                switch(IPC_GET_METHOD(call)){
     452                        case IPC_M_PHONE_HUNGUP:
     453                                keep_on_going = false;
     454                                res = EHANGUP;
     455                                break;
     456                        case NET_SOCKET:
     457                                socket_id = SOCKET_GET_SOCKET_ID(call);
     458                                res = socket_create(&local_sockets, app_phone, NULL, &socket_id);
     459                                SOCKET_SET_SOCKET_ID(answer, socket_id);
     460
     461                                if(res == EOK){
     462                                        if (tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){
     463                                                SOCKET_SET_DATA_FRAGMENT_SIZE(answer, packet_dimension->content);
     464                                        }
     465//                                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_UDP_FRAGMENT_SIZE);
     466                                        SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
     467                                        answer_count = 3;
     468                                }
     469                                break;
     470                        case NET_SOCKET_BIND:
     471                                res = data_receive((void **) &addr, &addrlen);
     472                                if(res == EOK){
     473                                        fibril_rwlock_write_lock(&udp_globals.lock);
     474                                        res = socket_bind(&local_sockets, &udp_globals.sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port);
     475                                        fibril_rwlock_write_unlock(&udp_globals.lock);
     476                                        free(addr);
     477                                }
     478                                break;
     479                        case NET_SOCKET_SENDTO:
     480                                res = data_receive((void **) &addr, &addrlen);
     481                                if(res == EOK){
     482                                        fibril_rwlock_write_lock(&udp_globals.lock);
     483                                        res = udp_sendto_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS(call), &size, SOCKET_GET_FLAGS(call));
     484                                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     485                                        if(res != EOK){
     486                                                fibril_rwlock_write_unlock(&udp_globals.lock);
     487                                        }else{
     488                                                answer_count = 2;
     489                                        }
     490                                        free(addr);
     491                                }
     492                                break;
     493                        case NET_SOCKET_RECVFROM:
     494                                fibril_rwlock_write_lock(&udp_globals.lock);
     495                                res = udp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen);
     496                                fibril_rwlock_write_unlock(&udp_globals.lock);
     497                                if(res > 0){
     498                                        SOCKET_SET_READ_DATA_LENGTH(answer, res);
     499                                        SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
     500                                        answer_count = 3;
     501                                        res = EOK;
     502                                }
     503                                break;
     504                        case NET_SOCKET_CLOSE:
     505                                fibril_rwlock_write_lock(&udp_globals.lock);
     506                                res = socket_destroy(udp_globals.net_phone, SOCKET_GET_SOCKET_ID(call), &local_sockets, &udp_globals.sockets, NULL);
     507                                fibril_rwlock_write_unlock(&udp_globals.lock);
     508                                break;
     509                        case NET_SOCKET_GETSOCKOPT:
     510                        case NET_SOCKET_SETSOCKOPT:
     511                        default:
     512                                res = ENOTSUP;
     513                                break;
     514                }
     515        }
     516
     517        // release the application phone
     518        ipc_hangup(app_phone);
     519
     520        // release all local sockets
     521        socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL);
     522
     523        return res;
     524}
     525
     526int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags){
     527        ERROR_DECLARE;
     528
     529        socket_core_ref socket;
     530        packet_t packet;
     531        packet_t next_packet;
     532        udp_header_ref header;
    463533        int index;
    464534        size_t total_length;
     
    469539        size_t headerlen;
    470540        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;
     541        packet_dimension_ref packet_dimension;
     542
     543        ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port));
    477544
    478545        socket = socket_cores_find(local_sockets, socket_id);
    479         if (!socket)
     546        if(! socket){
    480547                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;
     548        }
     549
     550        if((socket->port <= 0) && udp_globals.autobinding){
     551                // bind the socket to a random free port if not bound
     552//              do{
     553                        // try to find a free port
     554//                      fibril_rwlock_read_unlock(&udp_globals.lock);
     555//                      fibril_rwlock_write_lock(&udp_globals.lock);
     556                        // might be changed in the meantime
     557//                      if(socket->port <= 0){
     558                                if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){
     559//                                      fibril_rwlock_write_unlock(&udp_globals.lock);
     560//                                      fibril_rwlock_read_lock(&udp_globals.lock);
     561                                        return ERROR_CODE;
     562                                }
     563                                // set the next port as the search starting port number
     564                                udp_globals.last_used_port = socket->port;
     565//                      }
     566//                      fibril_rwlock_write_unlock(&udp_globals.lock);
     567//                      fibril_rwlock_read_lock(&udp_globals.lock);
     568                        // might be changed in the meantime
     569//              }while(socket->port <= 0);
     570        }
     571
     572        if(udp_globals.checksum_computing){
     573                if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){
     574                        return udp_release_and_return(packet, ERROR_CODE);
     575                }
     576                // get the device packet dimension
     577//              ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension));
     578        }
     579//      }else{
     580                // do not ask all the time
     581                ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));
    510582                packet_dimension = &udp_globals.packet_dimension;
    511583//      }
    512584
    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)
     585        // read the first packet fragment
     586        result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
     587        if(result < 0){
    517588                return result;
    518 
     589        }
    519590        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
     591        if(udp_globals.checksum_computing){
     592                checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet));
     593        }else{
    524594                checksum = 0;
    525 
    526         /* Prefix the UDP header */
     595        }
     596        // prefix the udp header
    527597        header = PACKET_PREFIX(packet, udp_header_t);
    528         if (!header)
     598        if(! header){
    529599                return udp_release_and_return(packet, ENOMEM);
    530 
     600        }
    531601        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)
     602        // read the rest of the packet fragments
     603        for(index = 1; index < fragments; ++ index){
     604                result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen);
     605                if(result < 0){
    538606                        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 
     607                }
     608                if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){
     609                        return udp_release_and_return(packet, ERROR_CODE);
     610                }
    544611                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 */
     612                if(udp_globals.checksum_computing){
     613                        checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet));
     614                }
     615        }
     616        // set the udp header
    553617        header->source_port = htons((socket->port > 0) ? socket->port : 0);
    554618        header->destination_port = htons(dest_port);
    555619        header->total_length = htons(total_length + sizeof(*header));
    556620        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) {
     621        if(udp_globals.checksum_computing){
     622                // update the pseudo header
     623                if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
    563624                        free(ip_header);
    564                         return udp_release_and_return(packet, rc);
    565                 }
    566 
    567                 /* Finish the checksum computation */
     625                        return udp_release_and_return(packet, ERROR_CODE);
     626                }
     627                // finish the checksum computation
    568628                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)));
     629                checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header));
     630                header->checksum = htons(flip_checksum(compact_checksum(checksum)));
    573631                free(ip_header);
    574         } else {
     632        }else{
    575633                device_id = DEVICE_INVALID_ID;
    576634        }
    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. */
     635        // prepare the first packet fragment
     636        if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){
     637                return udp_release_and_return(packet, ERROR_CODE);
     638        }
     639        // send the packet
    584640        fibril_rwlock_write_unlock(&udp_globals.lock);
    585 
    586         /* Send the packet */
    587641        ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
    588 
    589642        return EOK;
    590643}
    591644
    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;
     645int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){
     646        ERROR_DECLARE;
     647
     648        socket_core_ref socket;
    615649        int packet_id;
    616         packet_t *packet;
    617         udp_header_t *header;
    618         struct sockaddr *addr;
     650        packet_t packet;
     651        udp_header_ref header;
     652        struct sockaddr * addr;
    619653        size_t length;
    620         uint8_t *data;
     654        uint8_t * data;
    621655        int result;
    622         int rc;
    623 
    624         /* Find the socket */
     656
     657        // find the socket
    625658        socket = socket_cores_find(local_sockets, socket_id);
    626         if (!socket)
     659        if(! socket){
    627660                return ENOTSOCK;
    628 
    629         /* Get the next received packet */
     661        }
     662        // get the next received packet
    630663        packet_id = dyn_fifo_value(&socket->received);
    631         if (packet_id < 0)
     664        if(packet_id < 0){
    632665                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 */
     666        }
     667        ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, packet_id));
     668        // get udp header
    641669        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 */
     670        if(! data){
     671                pq_release_remote(udp_globals.net_phone, packet_id);
     672                return NO_DATA;
     673        }
     674        header = (udp_header_ref) data;
     675
     676        // set the source address port
    649677        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);
     678        if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){
     679                pq_release_remote(udp_globals.net_phone, packet_id);
     680                return ERROR_CODE;
    654681        }
    655682        *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)
    705 {
    706         int res;
    707         bool keep_on_going = true;
    708         socket_cores_t local_sockets;
    709         int app_phone = IPC_GET_PHONE(&call);
    710         struct sockaddr *addr;
    711         int socket_id;
    712         size_t addrlen;
    713         size_t size = 0;
    714         ipc_call_t answer;
    715         int answer_count;
    716         packet_dimension_t *packet_dimension;
    717 
    718         /*
    719          * Accept the connection
    720          *  - Answer the first IPC_M_CONNECT_TO_ME call.
    721          */
    722         res = EOK;
    723         answer_count = 0;
    724 
    725         /*
    726          * The client connection is only in one fibril and therefore no
    727          * additional locks are needed.
    728          */
    729 
    730         socket_cores_initialize(&local_sockets);
    731 
    732         while (keep_on_going) {
    733 
    734                 /* Answer the call */
    735                 answer_call(callid, res, &answer, answer_count);
    736 
    737                 /* Refresh data */
    738                 refresh_answer(&answer, &answer_count);
    739 
    740                 /* Get the next call */
    741                 callid = async_get_call(&call);
    742 
    743                 /* Process the call */
    744                 switch (IPC_GET_METHOD(call)) {
    745                 case IPC_M_PHONE_HUNGUP:
    746                         keep_on_going = false;
    747                         res = EHANGUP;
    748                         break;
    749 
    750                 case NET_SOCKET:
    751                         socket_id = SOCKET_GET_SOCKET_ID(call);
    752                         res = socket_create(&local_sockets, app_phone, NULL,
    753                             &socket_id);
    754                         SOCKET_SET_SOCKET_ID(answer, socket_id);
    755 
    756                         if (res != EOK)
    757                                 break;
    758                        
    759                         if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
    760                             &udp_globals.dimensions, DEVICE_INVALID_ID,
    761                             &packet_dimension) == EOK) {
    762                                 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    763                                     packet_dimension->content);
    764                         }
    765 
    766 //                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    767 //                          MAX_UDP_FRAGMENT_SIZE);
    768                         SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
    769                         answer_count = 3;
    770                         break;
    771 
    772                 case NET_SOCKET_BIND:
    773                         res = data_receive((void **) &addr, &addrlen);
    774                         if (res != EOK)
    775                                 break;
    776                         fibril_rwlock_write_lock(&udp_globals.lock);
    777                         res = socket_bind(&local_sockets, &udp_globals.sockets,
    778                             SOCKET_GET_SOCKET_ID(call), addr, addrlen,
    779                             UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
    780                             udp_globals.last_used_port);
    781                         fibril_rwlock_write_unlock(&udp_globals.lock);
    782                         free(addr);
    783                         break;
    784 
    785                 case NET_SOCKET_SENDTO:
    786                         res = data_receive((void **) &addr, &addrlen);
    787                         if (res != EOK)
    788                                 break;
    789 
    790                         fibril_rwlock_write_lock(&udp_globals.lock);
    791                         res = udp_sendto_message(&local_sockets,
    792                             SOCKET_GET_SOCKET_ID(call), addr, addrlen,
    793                             SOCKET_GET_DATA_FRAGMENTS(call), &size,
    794                             SOCKET_GET_FLAGS(call));
    795                         SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
    796 
    797                         if (res != EOK)
    798                                 fibril_rwlock_write_unlock(&udp_globals.lock);
    799                         else
    800                                 answer_count = 2;
    801                        
    802                         free(addr);
    803                         break;
    804 
    805                 case NET_SOCKET_RECVFROM:
    806                         fibril_rwlock_write_lock(&udp_globals.lock);
    807                         res = udp_recvfrom_message(&local_sockets,
    808                              SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
    809                              &addrlen);
    810                         fibril_rwlock_write_unlock(&udp_globals.lock);
    811 
    812                         if (res <= 0)
    813                                 break;
    814 
    815                         SOCKET_SET_READ_DATA_LENGTH(answer, res);
    816                         SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
    817                         answer_count = 3;
    818                         res = EOK;
    819                         break;
    820                        
    821                 case NET_SOCKET_CLOSE:
    822                         fibril_rwlock_write_lock(&udp_globals.lock);
    823                         res = socket_destroy(udp_globals.net_phone,
    824                             SOCKET_GET_SOCKET_ID(call), &local_sockets,
    825                             &udp_globals.sockets, NULL);
    826                         fibril_rwlock_write_unlock(&udp_globals.lock);
    827                         break;
    828 
    829                 case NET_SOCKET_GETSOCKOPT:
    830                 case NET_SOCKET_SETSOCKOPT:
    831                 default:
    832                         res = ENOTSUP;
    833                         break;
    834                 }
    835         }
    836 
    837         /* Release the application phone */
    838         ipc_hangup(app_phone);
    839 
    840         /* Release all local sockets */
    841         socket_cores_release(udp_globals.net_phone, &local_sockets,
    842             &udp_globals.sockets, NULL);
    843 
    844         return res;
    845 }
    846 
    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)
    862 {
    863         packet_t *packet;
    864         int rc;
    865 
    866         *answer_count = 0;
    867 
    868         switch (IPC_GET_METHOD(*call)) {
    869         case NET_TL_RECEIVED:
    870                 rc = packet_translate_remote(udp_globals.net_phone, &packet,
    871                     IPC_GET_PACKET(call));
    872                 if (rc != EOK)
    873                         return rc;
    874                 return udp_received_msg(IPC_GET_DEVICE(call), packet,
    875                     SERVICE_UDP, IPC_GET_ERROR(call));
    876         case IPC_M_CONNECT_TO_ME:
    877                 return udp_process_client_messages(callid, * call);
    878         }
    879 
    880         return ENOTSUP;
     683        // send the source address
     684        ERROR_PROPAGATE(data_reply(addr, * addrlen));
     685
     686        // trim the header
     687        ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));
     688
     689        // reply the packets
     690        ERROR_PROPAGATE(socket_reply_packets(packet, &length));
     691
     692        // release the packet
     693        dyn_fifo_pop(&socket->received);
     694        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     695        // return the total length
     696        return (int) length;
     697}
     698
     699int udp_release_and_return(packet_t packet, int result){
     700        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     701        return result;
    881702}
    882703
    883704/** Default thread for new connections.
    884705 *
    885  * @param[in] iid       The initial message identifier.
    886  * @param[in] icall     The initial message call structure.
     706 *  @param[in] iid The initial message identifier.
     707 *  @param[in] icall The initial message call structure.
     708 *
    887709 */
    888710static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     
    894716        ipc_answer_0(iid, EOK);
    895717       
    896         while (true) {
     718        while(true) {
    897719                ipc_call_t answer;
    898720                int answer_count;
     
    909731                    &answer_count);
    910732               
    911                 /*
    912                  * End if told to either by the message or the processing
    913                  * result.
    914                  */
    915                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    916                     (res == EHANGUP))
     733                /* End if said to either by the message or the processing result */
     734                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    917735                        return;
    918736               
     
    924742/** Starts the module.
    925743 *
    926  * @return              EOK on success.
    927  * @return              Other error codes as defined for each specific module
    928  *                      start function.
     744 *  @param argc The count of the command line arguments. Ignored parameter.
     745 *  @param argv The command line parameters. Ignored parameter.
     746 *
     747 *  @returns EOK on success.
     748 *  @returns Other error codes as defined for each specific module start function.
     749 *
    929750 */
    930751int main(int argc, char *argv[])
    931752{
    932         int rc;
     753        ERROR_DECLARE;
    933754       
    934755        /* Start the module */
    935         rc = tl_module_start_standalone(tl_client_connection);
    936         return rc;
     756        if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
     757                return ERROR_CODE;
     758       
     759        return EOK;
    937760}
    938761
Note: See TracChangeset for help on using the changeset viewer.