Ignore:
File:
1 edited

Legend:

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

    r348c589 rfb04cba8  
    3636 */
    3737
     38#include "udp.h"
     39#include "udp_header.h"
     40#include "udp_module.h"
     41
    3842#include <async.h>
    3943#include <fibril_synch.h>
    4044#include <malloc.h>
    4145#include <stdio.h>
     46#include <ipc/ipc.h>
    4247#include <ipc/services.h>
    4348#include <ipc/net.h>
     
    6065#include <ip_interface.h>
    6166#include <icmp_client.h>
    62 #include <icmp_remote.h>
     67#include <icmp_interface.h>
    6368#include <net_interface.h>
    6469#include <socket_core.h>
    6570#include <tl_common.h>
    66 #include <tl_remote.h>
    67 #include <tl_skel.h>
    68 
    69 #include "udp.h"
    70 #include "udp_header.h"
     71#include <tl_local.h>
     72#include <tl_interface.h>
    7173
    7274/** UDP module name. */
    73 #define NAME  "udp"
     75#define NAME    "UDP protocol"
    7476
    7577/** Default UDP checksum computing. */
     
    9092/** UDP global data.  */
    9193udp_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 */
     102int 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}
    92185
    93186/** Releases the packet and returns the result.
     
    97190 * @return              The result parameter.
    98191 */
    99 static int udp_release_and_return(packet_t *packet, int result)
     192static int udp_release_and_return(packet_t packet, int result)
    100193{
    101194        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
     
    112205 * @param[in] error     The packet error reporting service. Prefixes the
    113206 *                      received packet.
    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
     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
    117210 *                      an_addr_t.
    118  * @return              EINVAL if the packet does not contain any data.
    119  * @return              NO_DATA if the packet content is shorter than the user
     211 * @returns             EINVAL if the packet does not contain any data.
     212 * @returns             NO_DATA if the packet content is shorter than the user
    120213 *                      datagram header.
    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
     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
    124217 *                      ip_client_process_packet() function.
    125218 */
    126 static int udp_process_packet(device_id_t device_id, packet_t *packet,
     219static int udp_process_packet(device_id_t device_id, packet_t packet,
    127220    services_t error)
    128221{
     
    130223        size_t offset;
    131224        int result;
    132         udp_header_t *header;
    133         socket_core_t *socket;
    134         packet_t *next_packet;
     225        udp_header_ref header;
     226        socket_core_ref socket;
     227        packet_t next_packet;
    135228        size_t total_length;
    136229        uint32_t checksum;
    137230        int fragments;
    138         packet_t *tmp_packet;
     231        packet_t tmp_packet;
    139232        icmp_type_t type;
    140233        icmp_code_t code;
     
    142235        struct sockaddr *src;
    143236        struct sockaddr *dest;
    144         packet_dimension_t *packet_dimension;
     237        packet_dimension_ref packet_dimension;
    145238        int rc;
    146239
     
    184277
    185278        /* Get UDP header */
    186         header = (udp_header_t *) packet_get_data(packet);
     279        header = (udp_header_ref) packet_get_data(packet);
    187280        if (!header)
    188281                return udp_release_and_return(packet, NO_DATA);
     
    190283        /* Find the destination socket */
    191284        socket = socket_port_find(&udp_globals.sockets,
    192             ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
     285        ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
    193286        if (!socket) {
    194287                if (tl_prepare_icmp_packet(udp_globals.net_phone,
     
    300393        fibril_rwlock_write_unlock(&udp_globals.lock);
    301394        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
    302             (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0,
    303             (sysarg_t) fragments);
     395            (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,
     396            (ipcarg_t) fragments);
    304397
    305398        return EOK;
     
    316409 * @param[in] error     The packet error reporting service. Prefixes the
    317410 *                      received packet.
    318  * @return              EOK on success.
    319  * @return              Other error codes as defined for the
     411 * @returns             EOK on success.
     412 * @returns             Other error codes as defined for the
    320413 *                      udp_process_packet() function.
    321414 */
    322 static int udp_received_msg(device_id_t device_id, packet_t *packet,
     415static int udp_received_msg(device_id_t device_id, packet_t packet,
    323416    services_t receiver, services_t error)
    324417{
     
    331424
    332425        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  */
    341 static 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  */
    373 int 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;
    455426}
    456427
     
    468439 * @param[out] data_fragment_size The data fragment size in bytes.
    469440 * @param[in] flags     Various send flags.
    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
     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
    475446 *                      bound.
    476  * @return              ENOMEM if there is not enough memory left.
    477  * @return              Other error codes as defined for the
     447 * @returns             ENOMEM if there is not enough memory left.
     448 * @returns             Other error codes as defined for the
    478449 *                      socket_read_packet_data() function.
    479  * @return              Other error codes as defined for the
     450 * @returns             Other error codes as defined for the
    480451 *                      ip_client_prepare_packet() function.
    481  * @return              Other error codes as defined for the ip_send_msg()
     452 * @returns             Other error codes as defined for the ip_send_msg()
    482453 *                      function.
    483454 */
    484 static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id,
     455static int udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    485456    const struct sockaddr *addr, socklen_t addrlen, int fragments,
    486457    size_t *data_fragment_size, int flags)
    487458{
    488         socket_core_t *socket;
    489         packet_t *packet;
    490         packet_t *next_packet;
    491         udp_header_t *header;
     459        socket_core_ref socket;
     460        packet_t packet;
     461        packet_t next_packet;
     462        udp_header_ref header;
    492463        int index;
    493464        size_t total_length;
     
    498469        size_t headerlen;
    499470        device_id_t device_id;
    500         packet_dimension_t *packet_dimension;
    501         size_t size;
     471        packet_dimension_ref packet_dimension;
    502472        int rc;
    503 
    504         /* In case of error, do not update the data fragment size. */
    505         *data_fragment_size = 0;
    506473       
    507474        rc = tl_get_address_port(addr, addrlen, &dest_port);
     
    544511//      }
    545512
    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 
    556513        /* Read the first packet fragment */
    557514        result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
     
    642599 * @param[in] flags     Various receive flags.
    643600 * @param[out] addrlen  The source address length.
    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()
     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()
    650607 *                      function.
    651  * @return              Other error codes as defined for the data_reply()
     608 * @returns             Other error codes as defined for the data_reply()
    652609 *                      function.
    653610 */
    654 static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
     611static int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id,
    655612    int flags, size_t *addrlen)
    656613{
    657         socket_core_t *socket;
     614        socket_core_ref socket;
    658615        int packet_id;
    659         packet_t *packet;
    660         udp_header_t *header;
     616        packet_t packet;
     617        udp_header_ref header;
    661618        struct sockaddr *addr;
    662619        size_t length;
     
    687644                return udp_release_and_return(packet, NO_DATA);
    688645        }
    689         header = (udp_header_t *) data;
     646        header = (udp_header_ref) data;
    690647
    691648        /* Set the source address port */
     
    741698 * @param[in] callid    The message identifier.
    742699 * @param[in] call      The message parameters.
    743  * @return              EOK on success.
     700 * @returns             EOK on success.
    744701 *
    745702 * @see socket.h
     
    750707        bool keep_on_going = true;
    751708        socket_cores_t local_sockets;
    752         int app_phone = IPC_GET_PHONE(call);
     709        int app_phone = IPC_GET_PHONE(&call);
    753710        struct sockaddr *addr;
    754711        int socket_id;
     
    756713        size_t size;
    757714        ipc_call_t answer;
    758         size_t answer_count;
    759         packet_dimension_t *packet_dimension;
     715        int answer_count;
     716        packet_dimension_ref packet_dimension;
    760717
    761718        /*
     
    785742
    786743                /* Process the call */
    787                 switch (IPC_GET_IMETHOD(call)) {
     744                switch (IPC_GET_METHOD(call)) {
    788745                case IPC_M_PHONE_HUNGUP:
    789746                        keep_on_going = false;
     
    800757                                break;
    801758                       
    802                         size = MAX_UDP_FRAGMENT_SIZE;
    803759                        if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
    804760                            &udp_globals.dimensions, DEVICE_INVALID_ID,
    805761                            &packet_dimension) == EOK) {
    806                                 if (packet_dimension->content < size)
    807                                         size = packet_dimension->content;
     762                                SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     763                                    packet_dimension->content);
    808764                        }
    809                         SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     765
     766//                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     767//                          MAX_UDP_FRAGMENT_SIZE);
    810768                        SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
    811769                        answer_count = 3;
     
    813771
    814772                case NET_SOCKET_BIND:
    815                         res = async_data_write_accept((void **) &addr, false,
    816                             0, 0, 0, &addrlen);
     773                        res = data_receive((void **) &addr, &addrlen);
    817774                        if (res != EOK)
    818775                                break;
     
    827784
    828785                case NET_SOCKET_SENDTO:
    829                         res = async_data_write_accept((void **) &addr, false,
    830                             0, 0, 0, &addrlen);
     786                        res = data_receive((void **) &addr, &addrlen);
    831787                        if (res != EOK)
    832788                                break;
     
    880836
    881837        /* Release the application phone */
    882         async_hangup(app_phone);
     838        ipc_hangup(app_phone);
    883839
    884840        /* Release all local sockets */
     
    887843
    888844        return res;
    889 }
    890 
    891 /** Per-connection initialization
    892  *
    893  */
    894 void tl_connection(void)
    895 {
    896845}
    897846
     
    903852 * @param[out] answer_count The last parameter for the actual answer in the
    904853 *                      answer parameter.
    905  * @return              EOK on success.
    906  * @return              ENOTSUP if the message is not known.
     854 * @returns             EOK on success.
     855 * @returns             ENOTSUP if the message is not known.
    907856 *
    908857 * @see udp_interface.h
    909858 * @see IS_NET_UDP_MESSAGE()
    910859 */
    911 int tl_message(ipc_callid_t callid, ipc_call_t *call,
    912     ipc_call_t *answer, size_t *answer_count)
     860int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     861    ipc_call_t *answer, int *answer_count)
    913862{
     863        packet_t packet;
     864        int rc;
     865
    914866        *answer_count = 0;
    915867
    916         switch (IPC_GET_IMETHOD(*call)) {
     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));
    917876        case IPC_M_CONNECT_TO_ME:
    918                 return udp_process_client_messages(callid, *call);
     877                return udp_process_client_messages(callid, * call);
    919878        }
    920879
     
    922881}
    923882
     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 */
     888static 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 */
    924930int main(int argc, char *argv[])
    925931{
     932        int rc;
     933       
    926934        /* Start the module */
    927         return tl_module_start(SERVICE_UDP);
     935        rc = tl_module_start_standalone(tl_client_connection);
     936        return rc;
    928937}
    929938
Note: See TracChangeset for help on using the changeset viewer.