Changeset eb522e8 in mainline for uspace/srv/net/tl/udp/udp.c


Ignore:
Timestamp:
2011-06-01T08:43:42Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8d6c1f1
Parents:
9e2e715 (diff), e51a514 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Huuuuuge merge from development - all the work actually :)

File:
1 edited

Legend:

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

    r9e2e715 reb522e8  
    3636 */
    3737
    38 #include "udp.h"
    39 #include "udp_header.h"
    40 #include "udp_module.h"
    41 
    4238#include <async.h>
    4339#include <fibril_synch.h>
    4440#include <malloc.h>
    4541#include <stdio.h>
    46 #include <ipc/ipc.h>
    4742#include <ipc/services.h>
    4843#include <ipc/net.h>
     
    6560#include <ip_interface.h>
    6661#include <icmp_client.h>
    67 #include <icmp_interface.h>
     62#include <icmp_remote.h>
    6863#include <net_interface.h>
    6964#include <socket_core.h>
    7065#include <tl_common.h>
    71 #include <tl_local.h>
    72 #include <tl_interface.h>
     66#include <tl_remote.h>
     67#include <tl_skel.h>
     68
     69#include "udp.h"
     70#include "udp_header.h"
    7371
    7472/** UDP module name. */
    75 #define NAME    "UDP protocol"
     73#define NAME  "udp"
    7674
    7775/** Default UDP checksum computing. */
     
    9290/** UDP global data.  */
    9391udp_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  * @returns             EOK on success.
    100  * @returns             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_ref configuration;
    115         size_t count = sizeof(names) / sizeof(measured_string_t);
    116         char *data;
    117         int rc;
    118 
    119         fibril_rwlock_initialize(&udp_globals.lock);
    120         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);
    129                 return udp_globals.ip_phone;
    130         }
    131 
    132         /* Read default packet dimensions */
    133         rc = ip_packet_size_req(udp_globals.ip_phone, -1,
    134             &udp_globals.packet_dimension);
    135         if (rc != EOK) {
    136                 fibril_rwlock_write_unlock(&udp_globals.lock);
    137                 return rc;
    138         }
    139        
    140         rc = socket_ports_initialize(&udp_globals.sockets);
    141         if (rc != EOK) {
    142                 fibril_rwlock_write_unlock(&udp_globals.lock);
    143                 return rc;
    144         }
    145        
    146         rc = packet_dimensions_initialize(&udp_globals.dimensions);
    147         if (rc != EOK) {
    148                 socket_ports_destroy(&udp_globals.sockets);
    149                 fibril_rwlock_write_unlock(&udp_globals.lock);
    150                 return rc;
    151         }
    152        
    153         udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
    154         udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    155         udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    156 
    157         udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    158         udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
    159 
    160         /* Get configuration */
    161         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 
    179                 net_free_settings(configuration, data);
    180         }
    181 
    182         fibril_rwlock_write_unlock(&udp_globals.lock);
    183         return EOK;
    184 }
    18592
    18693/** Releases the packet and returns the result.
     
    19097 * @return              The result parameter.
    19198 */
    192 static int udp_release_and_return(packet_t packet, int result)
     99static int udp_release_and_return(packet_t *packet, int result)
    193100{
    194101        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     
    205112 * @param[in] error     The packet error reporting service. Prefixes the
    206113 *                      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
     114 * @return              EOK on success.
     115 * @return              EINVAL if the packet is not valid.
     116 * @return              EINVAL if the stored packet address is not the
    210117 *                      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
     118 * @return              EINVAL if the packet does not contain any data.
     119 * @return              NO_DATA if the packet content is shorter than the user
    213120 *                      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
     121 * @return              ENOMEM if there is not enough memory left.
     122 * @return              EADDRNOTAVAIL if the destination socket does not exist.
     123 * @return              Other error codes as defined for the
    217124 *                      ip_client_process_packet() function.
    218125 */
    219 static int udp_process_packet(device_id_t device_id, packet_t packet,
     126static int udp_process_packet(device_id_t device_id, packet_t *packet,
    220127    services_t error)
    221128{
     
    223130        size_t offset;
    224131        int result;
    225         udp_header_ref header;
    226         socket_core_ref socket;
    227         packet_t next_packet;
     132        udp_header_t *header;
     133        socket_core_t *socket;
     134        packet_t *next_packet;
    228135        size_t total_length;
    229136        uint32_t checksum;
    230137        int fragments;
    231         packet_t tmp_packet;
     138        packet_t *tmp_packet;
    232139        icmp_type_t type;
    233140        icmp_code_t code;
     
    235142        struct sockaddr *src;
    236143        struct sockaddr *dest;
    237         packet_dimension_ref packet_dimension;
     144        packet_dimension_t *packet_dimension;
    238145        int rc;
    239146
     
    277184
    278185        /* Get UDP header */
    279         header = (udp_header_ref) packet_get_data(packet);
     186        header = (udp_header_t *) packet_get_data(packet);
    280187        if (!header)
    281188                return udp_release_and_return(packet, NO_DATA);
     
    283190        /* Find the destination socket */
    284191        socket = socket_port_find(&udp_globals.sockets,
    285         ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     192            ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
    286193        if (!socket) {
    287194                if (tl_prepare_icmp_packet(udp_globals.net_phone,
     
    393300        fibril_rwlock_write_unlock(&udp_globals.lock);
    394301        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
    395             (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,
    396             (ipcarg_t) fragments);
     302            (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0,
     303            (sysarg_t) fragments);
    397304
    398305        return EOK;
     
    409316 * @param[in] error     The packet error reporting service. Prefixes the
    410317 *                      received packet.
    411  * @returns             EOK on success.
    412  * @returns             Other error codes as defined for the
     318 * @return              EOK on success.
     319 * @return              Other error codes as defined for the
    413320 *                      udp_process_packet() function.
    414321 */
    415 static int udp_received_msg(device_id_t device_id, packet_t packet,
     322static int udp_received_msg(device_id_t device_id, packet_t *packet,
    416323    services_t receiver, services_t error)
    417324{
     
    424331
    425332        return result;
     333}
     334
     335/** Process IPC messages from the IP module
     336 *
     337 * @param[in]     iid   Message identifier.
     338 * @param[in,out] icall Message parameters.
     339 *
     340 */
     341static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     342{
     343        packet_t *packet;
     344        int rc;
     345       
     346        while (true) {
     347                switch (IPC_GET_IMETHOD(*icall)) {
     348                case NET_TL_RECEIVED:
     349                        rc = packet_translate_remote(udp_globals.net_phone, &packet,
     350                            IPC_GET_PACKET(*icall));
     351                        if (rc == EOK)
     352                                rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet,
     353                                    SERVICE_UDP, IPC_GET_ERROR(*icall));
     354                       
     355                        async_answer_0(iid, (sysarg_t) rc);
     356                        break;
     357                default:
     358                        async_answer_0(iid, (sysarg_t) ENOTSUP);
     359                }
     360               
     361                iid = async_get_call(icall);
     362        }
     363}
     364
     365/** Initialize the UDP module.
     366 *
     367 * @param[in] net_phone Network module phone.
     368 *
     369 * @return EOK on success.
     370 * @return ENOMEM if there is not enough memory left.
     371 *
     372 */
     373int tl_initialize(int net_phone)
     374{
     375        measured_string_t names[] = {
     376                {
     377                        (uint8_t *) "UDP_CHECKSUM_COMPUTING",
     378                        22
     379                },
     380                {
     381                        (uint8_t *) "UDP_AUTOBINDING",
     382                        15
     383                }
     384        };
     385        measured_string_t *configuration;
     386        size_t count = sizeof(names) / sizeof(measured_string_t);
     387        uint8_t *data;
     388       
     389        fibril_rwlock_initialize(&udp_globals.lock);
     390        fibril_rwlock_write_lock(&udp_globals.lock);
     391       
     392        udp_globals.net_phone = net_phone;
     393       
     394        udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
     395       
     396        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
     397            SERVICE_UDP, udp_receiver);
     398        if (udp_globals.ip_phone < 0) {
     399                fibril_rwlock_write_unlock(&udp_globals.lock);
     400                return udp_globals.ip_phone;
     401        }
     402       
     403        /* Read default packet dimensions */
     404        int rc = ip_packet_size_req(udp_globals.ip_phone, -1,
     405            &udp_globals.packet_dimension);
     406        if (rc != EOK) {
     407                fibril_rwlock_write_unlock(&udp_globals.lock);
     408                return rc;
     409        }
     410       
     411        rc = socket_ports_initialize(&udp_globals.sockets);
     412        if (rc != EOK) {
     413                fibril_rwlock_write_unlock(&udp_globals.lock);
     414                return rc;
     415        }
     416       
     417        rc = packet_dimensions_initialize(&udp_globals.dimensions);
     418        if (rc != EOK) {
     419                socket_ports_destroy(&udp_globals.sockets, free);
     420                fibril_rwlock_write_unlock(&udp_globals.lock);
     421                return rc;
     422        }
     423       
     424        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
     425        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
     426        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
     427
     428        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
     429        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
     430
     431        /* Get configuration */
     432        configuration = &names[0];
     433        rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
     434            &data);
     435        if (rc != EOK) {
     436                socket_ports_destroy(&udp_globals.sockets, free);
     437                fibril_rwlock_write_unlock(&udp_globals.lock);
     438                return rc;
     439        }
     440       
     441        if (configuration) {
     442                if (configuration[0].value)
     443                        udp_globals.checksum_computing =
     444                            (configuration[0].value[0] == 'y');
     445               
     446                if (configuration[1].value)
     447                        udp_globals.autobinding =
     448                            (configuration[1].value[0] == 'y');
     449
     450                net_free_settings(configuration, data);
     451        }
     452
     453        fibril_rwlock_write_unlock(&udp_globals.lock);
     454        return EOK;
    426455}
    427456
     
    439468 * @param[out] data_fragment_size The data fragment size in bytes.
    440469 * @param[in] flags     Various send flags.
    441  * @returns             EOK on success.
    442  * @returns             EAFNOTSUPPORT if the address family is not supported.
    443  * @returns             ENOTSOCK if the socket is not found.
    444  * @returns             EINVAL if the address is invalid.
    445  * @returns             ENOTCONN if the sending socket is not and cannot be
     470 * @return              EOK on success.
     471 * @return              EAFNOTSUPPORT if the address family is not supported.
     472 * @return              ENOTSOCK if the socket is not found.
     473 * @return              EINVAL if the address is invalid.
     474 * @return              ENOTCONN if the sending socket is not and cannot be
    446475 *                      bound.
    447  * @returns             ENOMEM if there is not enough memory left.
    448  * @returns             Other error codes as defined for the
     476 * @return              ENOMEM if there is not enough memory left.
     477 * @return              Other error codes as defined for the
    449478 *                      socket_read_packet_data() function.
    450  * @returns             Other error codes as defined for the
     479 * @return              Other error codes as defined for the
    451480 *                      ip_client_prepare_packet() function.
    452  * @returns             Other error codes as defined for the ip_send_msg()
     481 * @return              Other error codes as defined for the ip_send_msg()
    453482 *                      function.
    454483 */
    455 static int udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
     484static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id,
    456485    const struct sockaddr *addr, socklen_t addrlen, int fragments,
    457486    size_t *data_fragment_size, int flags)
    458487{
    459         socket_core_ref socket;
    460         packet_t packet;
    461         packet_t next_packet;
    462         udp_header_ref header;
     488        socket_core_t *socket;
     489        packet_t *packet;
     490        packet_t *next_packet;
     491        udp_header_t *header;
    463492        int index;
    464493        size_t total_length;
     
    469498        size_t headerlen;
    470499        device_id_t device_id;
    471         packet_dimension_ref packet_dimension;
     500        packet_dimension_t *packet_dimension;
     501        size_t size;
    472502        int rc;
     503
     504        /* In case of error, do not update the data fragment size. */
     505        *data_fragment_size = 0;
    473506       
    474507        rc = tl_get_address_port(addr, addrlen, &dest_port);
     
    511544//      }
    512545
     546        /*
     547         * Update the data fragment size based on what the lower layers can
     548         * handle without fragmentation, but not more than the maximum allowed
     549         * for UDP.
     550         */
     551        size = MAX_UDP_FRAGMENT_SIZE;
     552        if (packet_dimension->content < size)
     553            size = packet_dimension->content;
     554        *data_fragment_size = size;
     555
    513556        /* Read the first packet fragment */
    514557        result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
     
    599642 * @param[in] flags     Various receive flags.
    600643 * @param[out] addrlen  The source address length.
    601  * @returns             The number of bytes received.
    602  * @returns             ENOTSOCK if the socket is not found.
    603  * @returns             NO_DATA if there are no received packets or data.
    604  * @returns             ENOMEM if there is not enough memory left.
    605  * @returns             EINVAL if the received address is not an IP address.
    606  * @returns             Other error codes as defined for the packet_translate()
     644 * @return              The number of bytes received.
     645 * @return              ENOTSOCK if the socket is not found.
     646 * @return              NO_DATA if there are no received packets or data.
     647 * @return              ENOMEM if there is not enough memory left.
     648 * @return              EINVAL if the received address is not an IP address.
     649 * @return              Other error codes as defined for the packet_translate()
    607650 *                      function.
    608  * @returns             Other error codes as defined for the data_reply()
     651 * @return              Other error codes as defined for the data_reply()
    609652 *                      function.
    610653 */
    611 static int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id,
     654static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
    612655    int flags, size_t *addrlen)
    613656{
    614         socket_core_ref socket;
     657        socket_core_t *socket;
    615658        int packet_id;
    616         packet_t packet;
    617         udp_header_ref header;
     659        packet_t *packet;
     660        udp_header_t *header;
    618661        struct sockaddr *addr;
    619662        size_t length;
     
    644687                return udp_release_and_return(packet, NO_DATA);
    645688        }
    646         header = (udp_header_ref) data;
     689        header = (udp_header_t *) data;
    647690
    648691        /* Set the source address port */
     
    698741 * @param[in] callid    The message identifier.
    699742 * @param[in] call      The message parameters.
    700  * @returns             EOK on success.
     743 * @return              EOK on success.
    701744 *
    702745 * @see socket.h
     
    707750        bool keep_on_going = true;
    708751        socket_cores_t local_sockets;
    709         int app_phone = IPC_GET_PHONE(&call);
     752        int app_phone = IPC_GET_PHONE(call);
    710753        struct sockaddr *addr;
    711754        int socket_id;
     
    713756        size_t size;
    714757        ipc_call_t answer;
    715         int answer_count;
    716         packet_dimension_ref packet_dimension;
     758        size_t answer_count;
     759        packet_dimension_t *packet_dimension;
    717760
    718761        /*
     
    742785
    743786                /* Process the call */
    744                 switch (IPC_GET_METHOD(call)) {
     787                switch (IPC_GET_IMETHOD(call)) {
    745788                case IPC_M_PHONE_HUNGUP:
    746789                        keep_on_going = false;
     
    757800                                break;
    758801                       
     802                        size = MAX_UDP_FRAGMENT_SIZE;
    759803                        if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
    760804                            &udp_globals.dimensions, DEVICE_INVALID_ID,
    761805                            &packet_dimension) == EOK) {
    762                                 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    763                                     packet_dimension->content);
     806                                if (packet_dimension->content < size)
     807                                        size = packet_dimension->content;
    764808                        }
    765 
    766 //                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    767 //                          MAX_UDP_FRAGMENT_SIZE);
     809                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
    768810                        SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
    769811                        answer_count = 3;
     
    771813
    772814                case NET_SOCKET_BIND:
    773                         res = data_receive((void **) &addr, &addrlen);
     815                        res = async_data_write_accept((void **) &addr, false,
     816                            0, 0, 0, &addrlen);
    774817                        if (res != EOK)
    775818                                break;
     
    784827
    785828                case NET_SOCKET_SENDTO:
    786                         res = data_receive((void **) &addr, &addrlen);
     829                        res = async_data_write_accept((void **) &addr, false,
     830                            0, 0, 0, &addrlen);
    787831                        if (res != EOK)
    788832                                break;
     
    836880
    837881        /* Release the application phone */
    838         ipc_hangup(app_phone);
     882        async_hangup(app_phone);
    839883
    840884        /* Release all local sockets */
     
    843887
    844888        return res;
     889}
     890
     891/** Per-connection initialization
     892 *
     893 */
     894void tl_connection(void)
     895{
    845896}
    846897
     
    852903 * @param[out] answer_count The last parameter for the actual answer in the
    853904 *                      answer parameter.
    854  * @returns             EOK on success.
    855  * @returns             ENOTSUP if the message is not known.
     905 * @return              EOK on success.
     906 * @return              ENOTSUP if the message is not known.
    856907 *
    857908 * @see udp_interface.h
    858909 * @see IS_NET_UDP_MESSAGE()
    859910 */
    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 
     911int tl_message(ipc_callid_t callid, ipc_call_t *call,
     912    ipc_call_t *answer, size_t *answer_count)
     913{
    866914        *answer_count = 0;
    867915
    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));
     916        switch (IPC_GET_IMETHOD(*call)) {
    876917        case IPC_M_CONNECT_TO_ME:
    877                 return udp_process_client_messages(callid, * call);
     918                return udp_process_client_messages(callid, *call);
    878919        }
    879920
     
    881922}
    882923
    883 /** Default thread for new connections.
    884  *
    885  * @param[in] iid       The initial message identifier.
    886  * @param[in] icall     The initial message call structure.
    887  */
    888 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    889 {
    890         /*
    891          * Accept the connection
    892          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    893          */
    894         ipc_answer_0(iid, EOK);
    895        
    896         while (true) {
    897                 ipc_call_t answer;
    898                 int answer_count;
    899                
    900                 /* Clear the answer structure */
    901                 refresh_answer(&answer, &answer_count);
    902                
    903                 /* Fetch the next message */
    904                 ipc_call_t call;
    905                 ipc_callid_t callid = async_get_call(&call);
    906                
    907                 /* Process the message */
    908                 int res = tl_module_message_standalone(callid, &call, &answer,
    909                     &answer_count);
    910                
    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))
    917                         return;
    918                
    919                 /* Answer the message */
    920                 answer_call(callid, res, &answer, answer_count);
    921         }
    922 }
    923 
    924 /** Starts the module.
    925  *
    926  * @returns             EOK on success.
    927  * @returns             Other error codes as defined for each specific module
    928  *                      start function.
    929  */
    930924int main(int argc, char *argv[])
    931925{
    932         int rc;
    933        
    934926        /* Start the module */
    935         rc = tl_module_start_standalone(tl_client_connection);
    936         return rc;
     927        return tl_module_start(SERVICE_UDP);
    937928}
    938929
Note: See TracChangeset for help on using the changeset viewer.