Changeset 92b42442 in mainline for uspace/srv/udp/assoc.c


Ignore:
Timestamp:
2012-04-05T21:16:00Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7094e196
Parents:
ee603c4
Message:

UDP datagram reception plus fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 * @}
Note: See TracChangeset for help on using the changeset viewer.