Changeset 48171fc4 in mainline for uspace/srv/net/dnsrsrv/transport.c


Ignore:
Timestamp:
2013-05-03T08:10:02Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a0d97f83
Parents:
fff7ef4
Message:

Single fibril for receiving responses. Request timeout.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/dnsrsrv/transport.c

    rfff7ef4 r48171fc4  
    3434 */
    3535
     36#include <adt/list.h>
    3637#include <errno.h>
     38#include <fibril_synch.h>
     39#include <io/log.h>
    3740#include <net/in.h>
    3841#include <net/inet.h>
    3942#include <net/socket.h>
     43#include <stdbool.h>
    4044#include <stdlib.h>
    4145
     
    4448#include "transport.h"
    4549
    46 #include <stdio.h>
    47 
    4850#define RECV_BUF_SIZE 4096
    4951
     52/** Request timeout (microseconds) */
     53#define REQ_TIMEOUT (5*1000*1000)
     54
     55typedef struct {
     56        link_t lreq;
     57        dns_message_t *req;
     58        dns_message_t *resp;
     59
     60        bool done;
     61        fibril_condvar_t done_cv;
     62        fibril_mutex_t done_lock;
     63
     64        int status;
     65} trans_req_t;
     66
    5067static uint8_t recv_buf[RECV_BUF_SIZE];
     68static fid_t recv_fid;
     69static int transport_fd = -1;
     70
     71/** Outstanding requests */
     72static LIST_INITIALIZE(treq_list);
     73static FIBRIL_MUTEX_INITIALIZE(treq_lock);
     74
     75static int transport_recv_fibril(void *arg);
     76
     77int transport_init(void)
     78{
     79        struct sockaddr_in laddr;
     80        int fd;
     81        fid_t fid;
     82        int rc;
     83
     84        laddr.sin_family = AF_INET;
     85        laddr.sin_port = htons(12345);
     86        laddr.sin_addr.s_addr = INADDR_ANY;
     87
     88        fd = -1;
     89
     90        fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
     91        if (fd < 0) {
     92                rc = EIO;
     93                goto error;
     94        }
     95
     96        rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
     97        if (rc != EOK)
     98                goto error;
     99
     100        transport_fd = fd;
     101
     102        fid = fibril_create(transport_recv_fibril, NULL);
     103        if (fid == 0)
     104                goto error;
     105
     106        fibril_add_ready(fid);
     107        recv_fid = fid;
     108        return EOK;
     109error:
     110        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing network socket.\n");
     111        if (fd >= 0)
     112                closesocket(fd);
     113        return rc;
     114}
     115
     116void transport_fini(void)
     117{
     118        if (transport_fd >= 0)
     119                closesocket(transport_fd);
     120}
     121
     122static trans_req_t *treq_create(dns_message_t *req)
     123{
     124        trans_req_t *treq;
     125
     126        treq = calloc(1, sizeof(trans_req_t));
     127        if (treq == NULL)
     128                return NULL;
     129
     130        treq->req = req;
     131        treq->resp = NULL;
     132        treq->done = false;
     133        fibril_condvar_initialize(&treq->done_cv);
     134        fibril_mutex_initialize(&treq->done_lock);
     135
     136        fibril_mutex_lock(&treq_lock);
     137        list_append(&treq->lreq, &treq_list);
     138        fibril_mutex_unlock(&treq_lock);
     139
     140        return treq;
     141}
     142
     143static void treq_destroy(trans_req_t *treq)
     144{
     145        if (link_in_use(&treq->lreq))
     146                list_remove(&treq->lreq);
     147        free(treq);
     148}
     149
     150static trans_req_t *treq_match_resp(dns_message_t *resp)
     151{
     152        assert(fibril_mutex_is_locked(&treq_lock));
     153
     154        list_foreach(treq_list, link) {
     155                trans_req_t *treq = list_get_instance(link, trans_req_t, lreq);
     156
     157                if (treq->req->id == resp->id) {
     158                        /* Match */
     159                        return treq;
     160                }
     161        }
     162
     163        return NULL;
     164}
     165
     166static void treq_complete(trans_req_t *treq, dns_message_t *resp)
     167{
     168        fibril_mutex_lock(&treq->done_lock);
     169        treq->done = true;
     170        treq->status = EOK;
     171        treq->resp = resp;
     172        fibril_mutex_unlock(&treq->done_lock);
     173
     174        fibril_condvar_broadcast(&treq->done_cv);
     175}
    51176
    52177int dns_request(dns_message_t *req, dns_message_t **rresp)
    53178{
    54         dns_message_t *resp;
    55179        int rc;
    56180        void *req_data;
    57181        size_t req_size;
    58182        struct sockaddr_in addr;
    59         struct sockaddr_in laddr;
     183        trans_req_t *treq;
     184
     185        req_data = NULL;
     186        treq = NULL;
     187
     188        addr.sin_family = AF_INET;
     189        addr.sin_port = htons(53);
     190        addr.sin_addr.s_addr = htonl((10 << 24) | (0 << 16) | (0 << 8) | 138);
     191
     192        rc = dns_message_encode(req, &req_data, &req_size);
     193        if (rc != EOK)
     194                goto error;
     195
     196        rc = sendto(transport_fd, req_data, req_size, 0,
     197            (struct sockaddr *)&addr, sizeof(addr));
     198        if (rc != EOK)
     199                goto error;
     200
     201        treq = treq_create(req);
     202        if (treq == NULL) {
     203                rc = ENOMEM;
     204                goto error;
     205        }
     206
     207        fibril_mutex_lock(&treq->done_lock);
     208        while (treq->done != true) {
     209                rc = fibril_condvar_wait_timeout(&treq->done_cv, &treq->done_lock,
     210                    REQ_TIMEOUT);
     211                if (rc == ETIMEOUT) {
     212                        fibril_mutex_unlock(&treq->done_lock);
     213                        rc = EIO;
     214                        goto error;
     215                }
     216        }
     217
     218        fibril_mutex_unlock(&treq->done_lock);
     219
     220        if (treq->status != EOK) {
     221                rc = treq->status;
     222                goto error;
     223        }
     224
     225        *rresp = treq->resp;
     226        treq_destroy(treq);
     227        free(req_data);
     228        return EOK;
     229error:
     230        if (treq != NULL)
     231                treq_destroy(treq);
     232        free(req_data);
     233        return rc;
     234}
     235
     236static int transport_recv_msg(dns_message_t **rresp)
     237{
    60238        struct sockaddr_in src_addr;
    61239        socklen_t src_addr_size;
    62240        size_t recv_size;
    63         int fd;
    64         int i;
    65 
    66         addr.sin_family = AF_INET;
    67         addr.sin_port = htons(53);
    68         addr.sin_addr.s_addr = htonl((10 << 24) | (0 << 16) | (0 << 8) | 138);
    69 
    70         laddr.sin_family = AF_INET;
    71         laddr.sin_port = htons(12345);
    72         laddr.sin_addr.s_addr = INADDR_ANY;
    73 
    74         req_data = NULL;
    75         fd = -1;
    76 
    77         rc = dns_message_encode(req, &req_data, &req_size);
    78         if (rc != EOK)
    79                 goto error;
    80 
    81         fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    82         if (fd < 0) {
    83                 rc = EIO;
    84                 goto error;
    85         }
    86 
    87         rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
    88         if (rc != EOK)
    89                 goto error;
    90 
    91         printf("fd=%d req_data=%p, req_size=%zu\n", fd, req_data, req_size);
    92         rc = sendto(fd, req_data, req_size, 0, (struct sockaddr *)&addr,
    93             sizeof(addr));
    94         if (rc != EOK)
    95                 goto error;
     241        dns_message_t *resp;
     242        int rc;
    96243
    97244        src_addr_size = sizeof(src_addr);
    98         rc = recvfrom(fd, recv_buf, RECV_BUF_SIZE, 0,
     245        rc = recvfrom(transport_fd, recv_buf, RECV_BUF_SIZE, 0,
    99246            (struct sockaddr *)&src_addr, &src_addr_size);
    100247        if (rc < 0) {
    101                 printf("recvfrom returns error - %d\n", rc);
     248                log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom returns error - %d\n", rc);
    102249                goto error;
    103250        }
    104251
    105252        recv_size = (size_t)rc;
    106 
    107         printf("received %d bytes\n", (int)recv_size);
    108         for (i = 0; i < (int)recv_size; i++) {
    109                 if (recv_buf[i] >= 32 && recv_buf[i] < 127)
    110                         printf("%c", recv_buf[i]);
    111                 else
    112                         printf("?");
    113         }
    114         printf("\n");
    115 
    116         printf("close socket\n");
    117         closesocket(fd);
    118         printf("free req_data\n");
    119         free(req_data);
    120253
    121254        rc = dns_message_decode(recv_buf, recv_size, &resp);
     
    129262
    130263error:
    131         if (req_data != NULL)
    132                 free(req_data);
    133         if (fd >= 0)
    134                 closesocket(fd);
    135264        return rc;
    136265}
    137266
     267static int transport_recv_fibril(void *arg)
     268{
     269        dns_message_t *resp;
     270        trans_req_t *treq;
     271        int rc;
     272
     273        while (true) {
     274                rc = transport_recv_msg(&resp);
     275                if (rc != EOK)
     276                        continue;
     277
     278                fibril_mutex_lock(&treq_lock);
     279                treq = treq_match_resp(resp);
     280                if (treq == NULL) {
     281                        fibril_mutex_unlock(&treq_lock);
     282                        continue;
     283                }
     284
     285                list_remove(&treq->lreq);
     286                fibril_mutex_unlock(&treq_lock);
     287
     288                treq_complete(treq, resp);
     289        }
     290
     291        return 0;
     292}
     293
    138294/** @}
    139295 */
Note: See TracChangeset for help on using the changeset viewer.