Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 92b42442 in mainline


Ignore:
Timestamp:
2012-04-05T21:16:00Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
7094e196
Parents:
ee603c4
Message:

UDP datagram reception plus fixes.

Location:
uspace
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/netecho/netecho.c

    ree603c4 r92b42442  
    373373                address_in.sin_family = AF_INET;
    374374                address_in.sin_port = htons(port);
     375                address_in.sin_addr.s_addr = INADDR_ANY;
    375376                address = (struct sockaddr *) &address_in;
    376377                addrlen = sizeof(address_in);
  • uspace/lib/c/include/net/in.h

    ree603c4 r92b42442  
    4545#define INET_ADDRSTRLEN  (4 * 3 + 3 + 1)
    4646
     47#define INADDR_ANY 0
     48
    4749/** Type definition of the INET address.
    4850 * @see in_addr
  • uspace/srv/tcp/conn.c

    ree603c4 r92b42442  
    309309}
    310310
    311 /** Compare two sockets.
    312  *
    313  * Two sockets are equal if the address is equal and the port number
    314  * is equal.
    315  */
     311/** Match socket with pattern. */
    316312static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
    317313{
     
    332328}
    333329
    334 /** Match socket with pattern. */
     330/** Match socket pair with pattern. */
    335331static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
    336332{
     
    357353tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
    358354{
    359         log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
     355        log_msg(LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
    360356
    361357        fibril_mutex_lock(&conn_list_lock);
  • uspace/srv/udp/assoc.c

    ree603c4 r92b42442  
    5151FIBRIL_MUTEX_INITIALIZE(assoc_list_lock);
    5252
     53static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *);
     54static int udp_assoc_queue_msg(udp_assoc_t *, udp_sockpair_t *, udp_msg_t *);
     55static bool udp_socket_match(udp_sock_t *, udp_sock_t *);
     56static bool udp_sockpair_match(udp_sockpair_t *, udp_sockpair_t *);
     57
    5358/** Create new association structure.
    5459 *
     
    6166        udp_assoc_t *assoc = NULL;
    6267
    63         /* Allocate connection structure */
     68        /* Allocate association structure */
    6469        assoc = calloc(1, sizeof(udp_assoc_t));
    6570        if (assoc == NULL)
     
    95100 * as an extra reference.
    96101 *
    97  * @param conn          Connection
     102 * @param assoc         Association
    98103 */
    99104static void udp_assoc_free(udp_assoc_t *assoc)
     
    103108        while (!list_empty(&assoc->rcv_queue)) {
    104109                link_t *link = list_first(&assoc->rcv_queue);
    105 //              ....;
     110                udp_rcv_queue_entry_t *rqe = list_get_instance(link,
     111                    udp_rcv_queue_entry_t, link);
    106112                list_remove(link);
     113
     114                udp_msg_delete(rqe->msg);
     115                free(rqe);
    107116        }
    108117
     
    219228        int rc;
    220229
     230        log_msg(LVL_DEBUG, "udp_assoc_send(%p, %p, %p)",
     231            assoc, fsock, msg);
     232
    221233        /* @a fsock can be used to override the foreign socket */
    222234        sp = assoc->ident;
     
    240252}
    241253
     254/** Get a received message.
     255 *
     256 * Pull one message from the association's receive queue.
     257 */
     258int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock)
     259{
     260        link_t *link;
     261        udp_rcv_queue_entry_t *rqe;
     262
     263        log_msg(LVL_DEBUG, "udp_assoc_recv()");
     264
     265        fibril_mutex_lock(&assoc->lock);
     266        while (list_empty(&assoc->rcv_queue)) {
     267                log_msg(LVL_DEBUG, "udp_assoc_recv() - waiting");
     268                fibril_condvar_wait(&assoc->rcv_queue_cv, &assoc->lock);
     269        }
     270
     271        log_msg(LVL_DEBUG, "udp_assoc_recv() - got a message");
     272        link = list_first(&assoc->rcv_queue);
     273        rqe = list_get_instance(link, udp_rcv_queue_entry_t, link);
     274        list_remove(link);
     275        fibril_mutex_unlock(&assoc->lock);
     276
     277        *msg = rqe->msg;
     278        *fsock = rqe->sp.foreign;
     279
     280        return EOK;
     281}
     282
     283/** Message received.
     284 *
     285 * Find the association to which the message belongs and queue it.
     286 */
     287void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg)
     288{
     289        udp_assoc_t *assoc;
     290        int rc;
     291
     292        log_msg(LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
     293
     294        assoc = udp_assoc_find_ref(rsp);
     295        if (assoc == NULL) {
     296                log_msg(LVL_DEBUG, "No association found. Message dropped.");
     297                /* XXX Generate ICMP error. */
     298                /* XXX Might propagate error directly by error return. */
     299                return;
     300        }
     301
     302        rc = udp_assoc_queue_msg(assoc, rsp, msg);
     303        if (rc != EOK) {
     304                log_msg(LVL_DEBUG, "Out of memory. Message dropped.");
     305                /* XXX Generate ICMP error? */
     306        }
     307}
     308
     309static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp,
     310    udp_msg_t *msg)
     311{
     312        udp_rcv_queue_entry_t *rqe;
     313
     314        log_msg(LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
     315            assoc, sp, msg);
     316
     317        rqe = calloc(1, sizeof(udp_rcv_queue_entry_t));
     318        if (rqe == NULL)
     319                return ENOMEM;
     320
     321        link_initialize(&rqe->link);
     322        rqe->sp = *sp;
     323        rqe->msg = msg;
     324
     325        fibril_mutex_lock(&assoc->lock);
     326        list_append(&rqe->link, &assoc->rcv_queue);
     327        fibril_mutex_unlock(&assoc->lock);
     328
     329        fibril_condvar_broadcast(&assoc->rcv_queue_cv);
     330
     331        return EOK;
     332}
     333
     334/** Match socket with pattern. */
     335static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt)
     336{
     337        log_msg(LVL_DEBUG, "udp_socket_match(sock=(%x,%u), pat=(%x,%u))",
     338            sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
     339
     340        if (patt->addr.ipv4 != UDP_IPV4_ANY &&
     341            patt->addr.ipv4 != sock->addr.ipv4)
     342                return false;
     343
     344        if (patt->port != UDP_PORT_ANY &&
     345            patt->port != sock->port)
     346                return false;
     347
     348        log_msg(LVL_DEBUG, " -> match");
     349
     350        return true;
     351}
     352
     353/** Match socket pair with pattern. */
     354static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern)
     355{
     356        log_msg(LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern);
     357
     358        if (!udp_socket_match(&sp->local, &pattern->local))
     359                return false;
     360
     361        if (!udp_socket_match(&sp->foreign, &pattern->foreign))
     362                return false;
     363
     364        log_msg(LVL_DEBUG, "Socket pair matched.");
     365        return true;
     366}
     367
     368
     369/** Find association structure for specified socket pair.
     370 *
     371 * An association is uniquely identified by a socket pair. Look up our
     372 * association map and return association structure based on socket pair.
     373 * The association reference count is bumped by one.
     374 *
     375 * @param sp    Socket pair
     376 * @return      Association structure or NULL if not found.
     377 */
     378static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp)
     379{
     380        log_msg(LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
     381
     382        fibril_mutex_lock(&assoc_list_lock);
     383
     384        list_foreach(assoc_list, link) {
     385                udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link);
     386                udp_sockpair_t *asp = &assoc->ident;
     387                log_msg(LVL_DEBUG, "compare with assoc (f:(%x,%u), l:(%x,%u))",
     388                    asp->foreign.addr.ipv4, asp->foreign.port,
     389                    asp->local.addr.ipv4, asp->local.port);
     390
     391                /* Skip unbound associations */
     392                if (asp->local.port == UDP_PORT_ANY)
     393                        continue;
     394
     395                if (udp_sockpair_match(sp, asp)) {
     396                        log_msg(LVL_DEBUG, "Returning assoc %p", assoc);
     397                        udp_assoc_addref(assoc);
     398                        fibril_mutex_unlock(&assoc_list_lock);
     399                        return assoc;
     400                }
     401        }
     402
     403        fibril_mutex_unlock(&assoc_list_lock);
     404        return NULL;
     405}
     406
     407
    242408/**
    243409 * @}
  • uspace/srv/udp/assoc.h

    ree603c4 r92b42442  
    4848extern void udp_assoc_set_local(udp_assoc_t *, udp_sock_t *);
    4949extern int udp_assoc_send(udp_assoc_t *, udp_sock_t *, udp_msg_t *);
     50extern int udp_assoc_recv(udp_assoc_t *, udp_msg_t **, udp_sock_t *);
     51extern void udp_assoc_received(udp_sockpair_t *, udp_msg_t *);
     52
    5053
    5154#endif
  • uspace/srv/udp/pdu.c

    ree603c4 r92b42442  
    9393}
    9494
    95 static udp_pdu_t *udp_pdu_new(void)
     95udp_pdu_t *udp_pdu_new(void)
    9696{
    9797        return calloc(1, sizeof(udp_pdu_t));
  • uspace/srv/udp/pdu.h

    ree603c4 r92b42442  
    4040#include "udp_type.h"
    4141
     42extern udp_pdu_t *udp_pdu_new(void);
    4243extern void udp_pdu_delete(udp_pdu_t *);
    4344extern int udp_pdu_decode(udp_pdu_t *, udp_sockpair_t *, udp_msg_t **);
  • uspace/srv/udp/sock.c

    ree603c4 r92b42442  
    114114        fibril_mutex_initialize(&sock->lock);
    115115        sock->client = client;
    116         sock->laddr.ipv4 = UDP_IPV4_ANY;
    117116
    118117        rc = udp_uc_create(&sock->assoc);
     
    189188
    190189        fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
    191         fsock.port = uint16_t_be2host(sock_core->port);
     190        fsock.port = sock_core->port;
    192191        urc = udp_uc_set_local(socket->assoc, &fsock);
    193192
     
    209208        }
    210209
     210        udp_sock_notify_data(sock_core);
     211
    211212        log_msg(LVL_DEBUG, " - success");
    212213        async_answer_0(callid, rc);
     
    286287
    287288        if (sock_core->port == 0) {
    288                 /* Implicitly bind socket */
     289                /* Implicitly bind socket to port */
    289290                rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
    290291                    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
     
    294295                        goto out;
    295296                }
     297
     298                udp_sock_notify_data(sock_core);
    296299        }
    297300
    298301        socket = (udp_sockdata_t *)sock_core->specific_data;
    299302        fibril_mutex_lock(&socket->lock);
     303
     304        if (socket->assoc->ident.local.addr.ipv4 == UDP_IPV4_ANY) {
     305                /* Determine local IP address */
     306                inet_addr_t loc_addr, rem_addr;
     307
     308                rem_addr.ipv4 = fsockp ? fsock.addr.ipv4 :
     309                    socket->assoc->ident.foreign.addr.ipv4;
     310
     311                rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
     312                if (rc != EOK) {
     313                        fibril_mutex_unlock(&socket->lock);
     314                        async_answer_0(callid, rc);
     315                        log_msg(LVL_DEBUG, "udp_sock_sendto: Failed to "
     316                            "determine local address.");
     317                        return;
     318                }
     319
     320                socket->assoc->ident.local.addr.ipv4 = loc_addr.ipv4;
     321                log_msg(LVL_DEBUG, "Local IP address is %x",
     322                    socket->assoc->ident.local.addr.ipv4);
     323        }
     324
    300325
    301326        assert(socket->assoc != NULL);
     
    394419        urc = udp_uc_receive(socket->assoc, buffer, FRAGMENT_SIZE, &data_len,
    395420            &xflags, &rsock);
    396         log_msg(LVL_DEBUG, "**** udp_uc_receive done");
     421        log_msg(LVL_DEBUG, "**** udp_uc_receive done, data_len=%zu", data_len);
    397422
    398423        switch (urc) {
     
    459484                rc = EOVERFLOW;
    460485
     486        log_msg(LVL_DEBUG, "read_data_length <- %zu", length);
    461487        SOCKET_SET_READ_DATA_LENGTH(answer, length);
    462         answer_call(callid, EOK, &answer, 1);
     488        SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(addr));
     489        answer_call(callid, EOK, &answer, 3);
    463490
    464491        /* Push one fragment notification to client's queue */
     
    526553
    527554        while (true) {
     555                log_msg(LVL_DEBUG, "udp_sock_connection: wait");
    528556                callid = async_get_call(&call);
    529557                if (!IPC_GET_IMETHOD(call))
    530558                        break;
    531559
    532                 log_msg(LVL_DEBUG, "udp_sock_connection: METHOD=%d\n",
     560                log_msg(LVL_DEBUG, "udp_sock_connection: METHOD=%d",
    533561                    (int)IPC_GET_IMETHOD(call));
    534562
  • uspace/srv/udp/ucall.c

    ree603c4 r92b42442  
    3636
    3737#include <io/log.h>
     38#include <macros.h>
    3839
    3940#include "assoc.h"
     
    9798    size_t *rcvd, xflags_t *xflags, udp_sock_t *fsock)
    9899{
    99 //      size_t xfer_size;
     100        size_t xfer_size;
     101        udp_msg_t *msg;
     102        int rc;
    100103
    101104        log_msg(LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
     105        rc = udp_assoc_recv(assoc, &msg, fsock);
     106        switch (rc) {
     107        }
     108
     109        xfer_size = min(size, msg->data_size);
     110        memcpy(buf, msg->data, xfer_size);
     111        *rcvd = xfer_size;
     112
    102113        return UDP_EOK;
    103114}
  • uspace/srv/udp/udp_inet.c

    ree603c4 r92b42442  
    4343#include <task.h>
    4444
     45#include "assoc.h"
     46#include "pdu.h"
    4547#include "std.h"
    4648#include "udp_inet.h"
     
    4850
    4951static int udp_inet_ev_recv(inet_dgram_t *dgram);
    50 //static void tcp_received_pdu(tcp_pdu_t *pdu);
     52static void udp_received_pdu(udp_pdu_t *pdu);
    5153
    5254static inet_ev_ops_t udp_inet_ev_ops = {
     
    5759static int udp_inet_ev_recv(inet_dgram_t *dgram)
    5860{
    59         uint8_t *pdu_raw;
    60         size_t pdu_raw_size;
     61        udp_pdu_t *pdu;
    6162
    6263        log_msg(LVL_DEBUG, "udp_inet_ev_recv()");
    6364
    64         pdu_raw = dgram->data;
    65         pdu_raw_size = dgram->size;
     65        pdu = udp_pdu_new();
     66        pdu->data = dgram->data;
     67        pdu->data_size = dgram->size;
    6668
    67         (void)pdu_raw;
    68         (void)pdu_raw_size;
    69         /* Split into header and payload. */
    70 /*
    71         log_msg(LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
     69        pdu->src.ipv4 = dgram->src.ipv4;
     70        pdu->dest.ipv4 = dgram->dest.ipv4;
     71        log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
     72            pdu->src.ipv4, pdu->dest.ipv4);
    7273
    73         tcp_pdu_t *pdu;
    74         size_t hdr_size;
    75         tcp_header_t *hdr;
    76         uint32_t data_offset;
     74        udp_received_pdu(pdu);
     75        udp_pdu_delete(pdu);
    7776
    78         if (pdu_raw_size < sizeof(tcp_header_t)) {
    79                 log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
    80                     pdu_raw_size, sizeof(tcp_header_t));
    81                 return EINVAL;
    82         }
    83 
    84         hdr = (tcp_header_t *)pdu_raw;
    85         data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
    86             uint16_t_be2host(hdr->doff_flags));
    87 
    88         hdr_size = sizeof(uint32_t) * data_offset;
    89 
    90         if (pdu_raw_size < hdr_size) {
    91                 log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
    92                     pdu_raw_size, hdr_size);
    93                 return EINVAL;
    94         }
    95 
    96         if (hdr_size < sizeof(tcp_header_t)) {
    97                 log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
    98                     hdr_size, sizeof(tcp_header_t));            return EINVAL;
    99         }
    100 
    101         log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
    102             pdu_raw_size, hdr_size);
    103         pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
    104             pdu_raw_size - hdr_size);
    105         if (pdu == NULL) {
    106                 log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
    107                 return ENOMEM;
    108         }
    109 
    110         pdu->src_addr.ipv4 = dgram->src.ipv4;
    111         pdu->dest_addr.ipv4 = dgram->dest.ipv4;
    112         log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
    113             pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
    114 
    115         tcp_received_pdu(pdu);
    116         tcp_pdu_delete(pdu);
    117 */
    11877        return EOK;
    11978}
     
    12483        int rc;
    12584        inet_dgram_t dgram;
     85
     86        log_msg(LVL_DEBUG, "udp_transmit_pdu()");
    12687
    12788        dgram.src.ipv4 = pdu->src.ipv4;
     
    139100
    140101/** Process received PDU. */
    141 /*
    142 static void tcp_received_pdu(tcp_pdu_t *pdu)
     102static void udp_received_pdu(udp_pdu_t *pdu)
    143103{
    144         tcp_segment_t *dseg;
    145         tcp_sockpair_t rident;
     104        udp_msg_t *dmsg;
     105        udp_sockpair_t rident;
    146106
    147         log_msg(LVL_DEBUG, "tcp_received_pdu()");
     107        log_msg(LVL_DEBUG, "udp_received_pdu()");
    148108
    149         if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
     109        if (udp_pdu_decode(pdu, &rident, &dmsg) != EOK) {
    150110                log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
    151111                return;
    152112        }
    153 */
    154         /* Insert decoded segment into rqueue */
    155 /*      tcp_rqueue_insert_seg(&rident, dseg);
     113
     114        /*
     115         * Insert decoded message into appropriate receive queue.
     116         * This transfers ownership of dmsg to the callee, we do not
     117         * free it.
     118         */
     119        udp_assoc_received(&rident, dmsg);
    156120}
    157 */
     121
    158122int udp_inet_init(void)
    159123{
  • uspace/srv/udp/udp_type.h

    ree603c4 r92b42442  
    6060enum netaddr {
    6161        UDP_IPV4_ANY = 0
     62};
     63
     64enum tcp_port {
     65        UDP_PORT_ANY = 0
    6266};
    6367
     
    137141        /** Connection */
    138142        udp_assoc_t *assoc;
    139         /** Local address */
    140         netaddr_t laddr;
    141143} udp_sockdata_t;
     144
     145typedef struct {
     146        /** Link to receive queue */
     147        link_t link;
     148        /** Socket pair */
     149        udp_sockpair_t sp;
     150        /** Message */
     151        udp_msg_t *msg;
     152} udp_rcv_queue_entry_t;
    142153
    143154#endif
Note: See TracChangeset for help on using the changeset viewer.