resolver.c 4.23 KB
Newer Older
pdw's avatar
iftop  
pdw committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * resolver.c:
 *
 */

#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>

#include "ns_hash.h"
chris's avatar
""    
chris committed
17
#include "iftop.h"
pdw's avatar
iftop  
pdw committed
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#define RESOLVE_QUEUE_LENGTH 20

struct in_addr resolve_queue[RESOLVE_QUEUE_LENGTH];

pthread_cond_t resolver_queue_cond;
pthread_mutex_t resolver_queue_mutex;

hash_type* ns_hash;

int head;
int tail;

void resolver_worker(void* ptr) {
    struct timespec delay;
33
    int thread_number = *(int*)ptr;
pdw's avatar
iftop  
pdw committed
34
35
    delay.tv_sec = 0;
    delay.tv_nsec = 500;
36
    pthread_mutex_lock(&resolver_queue_mutex);
pdw's avatar
iftop  
pdw committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    while(1) {
        /* Wait until we are told that an address has been added to the 
         * queue
         */
        pthread_cond_wait(&resolver_queue_cond, &resolver_queue_mutex);

        /* Keep resolving until the queue is empty */
        while(head != tail) {
            struct in_addr addr = resolve_queue[tail];
            struct hostent hostbuf, *hp;
            size_t hstbuflen;
            char *tmphstbuf;
            int res;
            int herr;

            /* mutex always locked at this point */

            tail = (tail + 1) % RESOLVE_QUEUE_LENGTH;

56
57
58
            pthread_mutex_unlock(&resolver_queue_mutex);

            fprintf(stderr,"Thread %d resolving: %s\n", thread_number, inet_ntoa(addr));
pdw's avatar
iftop  
pdw committed
59
60
61
62


            hstbuflen = 1024;
            /* Allocate buffer, remember to free it to avoid memory leakage.  */            
chris's avatar
""    
chris committed
63
            tmphstbuf = xmalloc (hstbuflen);
pdw's avatar
iftop  
pdw committed
64
65
66
67
68
69
70
71
72

            while ((res = gethostbyaddr_r (&addr, sizeof(addr), AF_INET,
                                           &hostbuf, tmphstbuf, hstbuflen,
                                           &hp, &herr)) == ERANGE) {
                /* Enlarge the buffer.  */
                hstbuflen *= 2;
                tmphstbuf = realloc (tmphstbuf, hstbuflen);
              }

73
74
            fprintf(stderr,"Thread %d resolved: %s\n", thread_number, inet_ntoa(addr));

pdw's avatar
iftop  
pdw committed
75
76
77
            /*
             * Store the result in ns_hash
             */
78
            pthread_mutex_lock(&resolver_queue_mutex);
pdw's avatar
iftop  
pdw committed
79
80
81
82
83
84
85
86
87
88
89
90
91

            /*  Check for errors.  */
            if (res || hp == NULL) {
                /* failed */
                //printf("[ Did not resolve %s ]\n", inet_ntoa(addr));
                /* Leave the unresolved IP in the hash */
            }
            else {
                /* success */
                char* hostname;
                //printf("[ Resolved: %s ]\n", hp->h_name);
                if(hash_find(ns_hash, &addr, (void**)&hostname) == HASH_STATUS_OK) {
                    hash_delete(ns_hash, &addr);
chris's avatar
""    
chris committed
92
                    xfree(hostname);
pdw's avatar
iftop  
pdw committed
93
94
95
96
97
98
99
100
                }
                else {
                    //printf("[ Warning: Could not find hash entry for key: %s ]\n", inet_ntoa(addr));
                }
                hostname = strdup(hp->h_name);
                hash_insert(ns_hash, &addr, (void*)hostname);

            }
chris's avatar
""    
chris committed
101
            xfree(tmphstbuf);
pdw's avatar
iftop  
pdw committed
102
103
104
105
106
        }
    }
}

void resolver_initialise() {
107
108
    int* n;
    int i;
pdw's avatar
iftop  
pdw committed
109
110
111
112
113
114
115
116
    pthread_t thread;
    head = tail = 0;

    ns_hash = ns_hash_create();
    
    pthread_mutex_init(&resolver_queue_mutex, NULL);
    pthread_cond_init(&resolver_queue_cond, NULL);

117
118
119
120
121
    for(i = 0; i < 2; i++) {
        n = (int*)xmalloc(sizeof n);
        *n = i;
        pthread_create(&thread, NULL, (void*)&resolver_worker, (void*)n);
    }
pdw's avatar
iftop  
pdw committed
122
123
124
125
126

}

void resolve(struct in_addr* addr, char* result, int buflen) {
    char* hostname;
127
    int added = 0;
pdw's avatar
iftop  
pdw committed
128

129
    pthread_mutex_lock(&resolver_queue_mutex);
pdw's avatar
iftop  
pdw committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143

    if(hash_find(ns_hash, addr, (void**)&hostname) == HASH_STATUS_OK) {
        /* Found => already resolved, or on the queue */
    }
    else {
        hostname = strdup(inet_ntoa(*addr));
        hash_insert(ns_hash, addr, hostname);

        if(((head + 1) % RESOLVE_QUEUE_LENGTH) == tail) {
            /* queue full */
        }
        else {
            resolve_queue[head] = *addr;
            head = (head + 1) % RESOLVE_QUEUE_LENGTH;
144
            added = 1;
pdw's avatar
iftop  
pdw committed
145
146
        }
    }
147
148
149
150
151
    pthread_mutex_unlock(&resolver_queue_mutex);

    if(added == 1) {
        pthread_cond_signal(&resolver_queue_cond);
    }
pdw's avatar
iftop  
pdw committed
152
153
154
155
156
157

    if(result != NULL && buflen > 1) {
        strncpy(result, hostname, buflen - 1);
        result[buflen - 1] = '\0';
    }
}