~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/pjlib-util/src/pjlib-util-test/resolver_test.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier, Francois Marier, Mark Purcell
  • Date: 2014-10-18 15:08:50 UTC
  • mfrom: (1.1.12)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20141018150850-2exfk34ckb15pcwi
Tags: 1.4.1-0.1
[ Francois Marier ]
* Non-maintainer upload
* New upstream release (closes: #759576, #741130)
  - debian/rules +PJPROJECT_VERSION := 2.2.1
  - add upstream patch to fix broken TLS support
  - add patch to fix pjproject regression

[ Mark Purcell ]
* Build-Depends:
  - sflphone-daemon + libavformat-dev, libavcodec-dev, libswscale-dev,
  libavdevice-dev, libavutil-dev
  - sflphone-gnome + libclutter-gtk-1.0-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: resolver_test.c 4537 2013-06-19 06:47:43Z riza $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pjlib-util.h>
 
21
#include <pjlib.h>
 
22
#include "test.h"
 
23
 
 
24
 
 
25
#define THIS_FILE   "srv_resolver_test.c"
 
26
 
 
27
////////////////////////////////////////////////////////////////////////////
 
28
/*
 
29
 * TODO: create various invalid DNS packets.
 
30
 */
 
31
 
 
32
 
 
33
////////////////////////////////////////////////////////////////////////////
 
34
 
 
35
 
 
36
#define ACTION_REPLY    0
 
37
#define ACTION_IGNORE   -1
 
38
#define ACTION_CB       -2
 
39
 
 
40
static struct server_t
 
41
{
 
42
    pj_sock_t        sock;
 
43
    pj_uint16_t      port;
 
44
    pj_thread_t     *thread;
 
45
 
 
46
    /* Action:
 
47
     *  0:    reply with the response in resp.
 
48
     * -1:    ignore query (to simulate timeout).
 
49
     * other: reply with that error
 
50
     */
 
51
    int             action;
 
52
 
 
53
    pj_dns_parsed_packet    resp;
 
54
    void                  (*action_cb)(const pj_dns_parsed_packet *pkt,
 
55
                                       pj_dns_parsed_packet **p_res);
 
56
 
 
57
    unsigned        pkt_count;
 
58
 
 
59
} g_server[2];
 
60
 
 
61
static pj_pool_t *pool;
 
62
static pj_dns_resolver *resolver;
 
63
static pj_bool_t thread_quit;
 
64
static pj_timer_heap_t *timer_heap;
 
65
static pj_ioqueue_t *ioqueue;
 
66
static pj_thread_t *poll_thread;
 
67
static pj_sem_t *sem;
 
68
static pj_dns_settings set;
 
69
 
 
70
#define MAX_LABEL   32
 
71
 
 
72
struct label_tab
 
73
{
 
74
    unsigned count;
 
75
 
 
76
    struct {
 
77
        unsigned pos;
 
78
        pj_str_t label;
 
79
    } a[MAX_LABEL];
 
80
};
 
81
 
 
82
static void write16(pj_uint8_t *p, pj_uint16_t val)
 
83
{
 
84
    p[0] = (pj_uint8_t)(val >> 8);
 
85
    p[1] = (pj_uint8_t)(val & 0xFF);
 
86
}
 
87
 
 
88
static void write32(pj_uint8_t *p, pj_uint32_t val)
 
89
{
 
90
    val = pj_htonl(val);
 
91
    pj_memcpy(p, &val, 4);
 
92
}
 
93
 
 
94
static int print_name(pj_uint8_t *pkt, int size,
 
95
                      pj_uint8_t *pos, const pj_str_t *name,
 
96
                      struct label_tab *tab)
 
97
{
 
98
    pj_uint8_t *p = pos;
 
99
    const char *endlabel, *endname;
 
100
    unsigned i;
 
101
    pj_str_t label;
 
102
 
 
103
    /* Check if name is in the table */
 
104
    for (i=0; i<tab->count; ++i) {
 
105
        if (pj_strcmp(&tab->a[i].label, name)==0)
 
106
            break;
 
107
    }
 
108
 
 
109
    if (i != tab->count) {
 
110
        write16(p, (pj_uint16_t)(tab->a[i].pos | (0xc0 << 8)));
 
111
        return 2;
 
112
    } else {
 
113
        if (tab->count < MAX_LABEL) {
 
114
            tab->a[tab->count].pos = (unsigned)(p-pkt);
 
115
            tab->a[tab->count].label.ptr = (char*)(p+1);
 
116
            tab->a[tab->count].label.slen = name->slen;
 
117
            ++tab->count;
 
118
        }
 
119
    }
 
120
 
 
121
    endlabel = name->ptr;
 
122
    endname = name->ptr + name->slen;
 
123
 
 
124
    label.ptr = (char*)name->ptr;
 
125
 
 
126
    while (endlabel != endname) {
 
127
 
 
128
        while (endlabel != endname && *endlabel != '.')
 
129
            ++endlabel;
 
130
 
 
131
        label.slen = (endlabel - label.ptr);
 
132
 
 
133
        if (size < label.slen+1)
 
134
            return -1;
 
135
 
 
136
        *p = (pj_uint8_t)label.slen;
 
137
        pj_memcpy(p+1, label.ptr, label.slen);
 
138
 
 
139
        size -= (int)(label.slen+1);
 
140
        p += (label.slen+1);
 
141
 
 
142
        if (endlabel != endname && *endlabel == '.')
 
143
            ++endlabel;
 
144
        label.ptr = (char*)endlabel;
 
145
    }
 
146
 
 
147
    if (size == 0)
 
148
        return -1;
 
149
 
 
150
    *p++ = '\0';
 
151
 
 
152
    return (int)(p-pos);
 
153
}
 
154
 
 
155
static int print_rr(pj_uint8_t *pkt, int size, pj_uint8_t *pos,
 
156
                    const pj_dns_parsed_rr *rr, struct label_tab *tab)
 
157
{
 
158
    pj_uint8_t *p = pos;
 
159
    int len;
 
160
 
 
161
    len = print_name(pkt, size, pos, &rr->name, tab);
 
162
    if (len < 0)
 
163
        return -1;
 
164
 
 
165
    p += len;
 
166
    size -= len;
 
167
 
 
168
    if (size < 8)
 
169
        return -1;
 
170
 
 
171
    pj_assert(rr->dnsclass == 1);
 
172
 
 
173
    write16(p+0, (pj_uint16_t)rr->type);        /* type     */
 
174
    write16(p+2, (pj_uint16_t)rr->dnsclass);    /* class    */
 
175
    write32(p+4, rr->ttl);                      /* TTL      */
 
176
 
 
177
    p += 8;
 
178
    size -= 8;
 
179
 
 
180
    if (rr->type == PJ_DNS_TYPE_A) {
 
181
 
 
182
        if (size < 6)
 
183
            return -1;
 
184
 
 
185
        /* RDLEN is 4 */
 
186
        write16(p, 4);
 
187
 
 
188
        /* Address */
 
189
        pj_memcpy(p+2, &rr->rdata.a.ip_addr, 4);
 
190
 
 
191
        p += 6;
 
192
        size -= 6;
 
193
 
 
194
    } else if (rr->type == PJ_DNS_TYPE_CNAME ||
 
195
               rr->type == PJ_DNS_TYPE_NS ||
 
196
               rr->type == PJ_DNS_TYPE_PTR) {
 
197
 
 
198
        if (size < 4)
 
199
            return -1;
 
200
 
 
201
        len = print_name(pkt, size-2, p+2, &rr->rdata.cname.name, tab);
 
202
        if (len < 0)
 
203
            return -1;
 
204
 
 
205
        write16(p, (pj_uint16_t)len);
 
206
 
 
207
        p += (len + 2);
 
208
        size -= (len + 2);
 
209
 
 
210
    } else if (rr->type == PJ_DNS_TYPE_SRV) {
 
211
 
 
212
        if (size < 10)
 
213
            return -1;
 
214
 
 
215
        write16(p+2, rr->rdata.srv.prio);   /* Priority */
 
216
        write16(p+4, rr->rdata.srv.weight); /* Weight */
 
217
        write16(p+6, rr->rdata.srv.port);   /* Port */
 
218
 
 
219
        /* Target */
 
220
        len = print_name(pkt, size-8, p+8, &rr->rdata.srv.target, tab);
 
221
        if (len < 0)
 
222
            return -1;
 
223
 
 
224
        /* RDLEN */
 
225
        write16(p, (pj_uint16_t)(len + 6));
 
226
 
 
227
        p += (len + 8);
 
228
        size -= (len + 8);
 
229
 
 
230
    } else {
 
231
        pj_assert(!"Not supported");
 
232
        return -1;
 
233
    }
 
234
 
 
235
    return (int)(p-pos);
 
236
}
 
237
 
 
238
static int print_packet(const pj_dns_parsed_packet *rec, pj_uint8_t *pkt,
 
239
                        int size)
 
240
{
 
241
    pj_uint8_t *p = pkt;
 
242
    struct label_tab tab;
 
243
    int i, len;
 
244
 
 
245
    tab.count = 0;
 
246
 
 
247
#if 0
 
248
    pj_enter_critical_section();
 
249
    PJ_LOG(3,(THIS_FILE, "Sending response:"));
 
250
    pj_dns_dump_packet(rec);
 
251
    pj_leave_critical_section();
 
252
#endif
 
253
 
 
254
    pj_assert(sizeof(pj_dns_hdr)==12);
 
255
    if (size < (int)sizeof(pj_dns_hdr))
 
256
        return -1;
 
257
 
 
258
    /* Initialize header */
 
259
    write16(p+0,  rec->hdr.id);
 
260
    write16(p+2,  rec->hdr.flags);
 
261
    write16(p+4,  rec->hdr.qdcount);
 
262
    write16(p+6,  rec->hdr.anscount);
 
263
    write16(p+8,  rec->hdr.nscount);
 
264
    write16(p+10, rec->hdr.arcount);
 
265
 
 
266
    p = pkt + sizeof(pj_dns_hdr);
 
267
    size -= sizeof(pj_dns_hdr);
 
268
 
 
269
    /* Print queries */
 
270
    for (i=0; i<rec->hdr.qdcount; ++i) {
 
271
 
 
272
        len = print_name(pkt, size, p, &rec->q[i].name, &tab);
 
273
        if (len < 0)
 
274
            return -1;
 
275
 
 
276
        p += len;
 
277
        size -= len;
 
278
 
 
279
        if (size < 4)
 
280
            return -1;
 
281
 
 
282
        /* Set type */
 
283
        write16(p+0, (pj_uint16_t)rec->q[i].type);
 
284
 
 
285
        /* Set class (IN=1) */
 
286
        pj_assert(rec->q[i].dnsclass == 1);
 
287
        write16(p+2, rec->q[i].dnsclass);
 
288
 
 
289
        p += 4;
 
290
    }
 
291
 
 
292
    /* Print answers */
 
293
    for (i=0; i<rec->hdr.anscount; ++i) {
 
294
        len = print_rr(pkt, size, p, &rec->ans[i], &tab);
 
295
        if (len < 0)
 
296
            return -1;
 
297
 
 
298
        p += len;
 
299
        size -= len;
 
300
    }
 
301
 
 
302
    /* Print NS records */
 
303
    for (i=0; i<rec->hdr.nscount; ++i) {
 
304
        len = print_rr(pkt, size, p, &rec->ns[i], &tab);
 
305
        if (len < 0)
 
306
            return -1;
 
307
 
 
308
        p += len;
 
309
        size -= len;
 
310
    }
 
311
 
 
312
    /* Print additional records */
 
313
    for (i=0; i<rec->hdr.arcount; ++i) {
 
314
        len = print_rr(pkt, size, p, &rec->arr[i], &tab);
 
315
        if (len < 0)
 
316
            return -1;
 
317
 
 
318
        p += len;
 
319
        size -= len;
 
320
    }
 
321
 
 
322
    return (int)(p - pkt);
 
323
}
 
324
 
 
325
 
 
326
static int server_thread(void *p)
 
327
{
 
328
    struct server_t *srv = (struct server_t*)p;
 
329
 
 
330
    while (!thread_quit) {
 
331
        pj_fd_set_t rset;
 
332
        pj_time_val timeout = {0, 500};
 
333
        pj_sockaddr_in src_addr;
 
334
        pj_dns_parsed_packet *req;
 
335
        char pkt[1024];
 
336
        pj_ssize_t pkt_len;
 
337
        int rc, src_len;
 
338
 
 
339
        PJ_FD_ZERO(&rset);
 
340
        PJ_FD_SET(srv->sock, &rset);
 
341
 
 
342
        rc = pj_sock_select((int)(srv->sock+1), &rset, NULL, NULL, &timeout);
 
343
        if (rc != 1)
 
344
            continue;
 
345
 
 
346
        src_len = sizeof(src_addr);
 
347
        pkt_len = sizeof(pkt);
 
348
        rc = pj_sock_recvfrom(srv->sock, pkt, &pkt_len, 0, 
 
349
                              &src_addr, &src_len);
 
350
        if (rc != 0) {
 
351
            app_perror("Server error receiving packet", rc);
 
352
            continue;
 
353
        }
 
354
 
 
355
        PJ_LOG(5,(THIS_FILE, "Server %d processing packet", srv - &g_server[0]));
 
356
        srv->pkt_count++;
 
357
 
 
358
        rc = pj_dns_parse_packet(pool, pkt, (unsigned)pkt_len, &req);
 
359
        if (rc != PJ_SUCCESS) {
 
360
            app_perror("server error parsing packet", rc);
 
361
            continue;
 
362
        }
 
363
 
 
364
        /* Verify packet */
 
365
        pj_assert(req->hdr.qdcount == 1);
 
366
        pj_assert(req->q[0].dnsclass == 1);
 
367
 
 
368
        /* Simulate network RTT */
 
369
        pj_thread_sleep(50);
 
370
 
 
371
        if (srv->action == ACTION_IGNORE) {
 
372
            continue;
 
373
        } else if (srv->action == ACTION_REPLY) {
 
374
            srv->resp.hdr.id = req->hdr.id;
 
375
            pkt_len = print_packet(&srv->resp, (pj_uint8_t*)pkt, sizeof(pkt));
 
376
            pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
 
377
        } else if (srv->action == ACTION_CB) {
 
378
            pj_dns_parsed_packet *resp;
 
379
            (*srv->action_cb)(req, &resp);
 
380
            resp->hdr.id = req->hdr.id;
 
381
            pkt_len = print_packet(resp, (pj_uint8_t*)pkt, sizeof(pkt));
 
382
            pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
 
383
        } else if (srv->action > 0) {
 
384
            req->hdr.flags |= PJ_DNS_SET_RCODE(srv->action);
 
385
            pkt_len = print_packet(req, (pj_uint8_t*)pkt, sizeof(pkt));
 
386
            pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
 
387
        }
 
388
    }
 
389
 
 
390
    return 0;
 
391
}
 
392
 
 
393
static int poll_worker_thread(void *p)
 
394
{
 
395
    PJ_UNUSED_ARG(p);
 
396
 
 
397
    while (!thread_quit) {
 
398
        pj_time_val delay = {0, 100};
 
399
        pj_timer_heap_poll(timer_heap, NULL);
 
400
        pj_ioqueue_poll(ioqueue, &delay);
 
401
    }
 
402
 
 
403
    return 0;
 
404
}
 
405
 
 
406
static void destroy(void);
 
407
 
 
408
static int init(void)
 
409
{
 
410
    pj_status_t status;
 
411
    pj_str_t nameservers[2];
 
412
    pj_uint16_t ports[2];
 
413
    int i;
 
414
 
 
415
    nameservers[0] = pj_str("127.0.0.1");
 
416
    ports[0] = 5553;
 
417
    nameservers[1] = pj_str("127.0.0.1");
 
418
    ports[1] = 5554;
 
419
 
 
420
    g_server[0].port = ports[0];
 
421
    g_server[1].port = ports[1];
 
422
 
 
423
    pool = pj_pool_create(mem, NULL, 2000, 2000, NULL);
 
424
 
 
425
    status = pj_sem_create(pool, NULL, 0, 2, &sem);
 
426
    pj_assert(status == PJ_SUCCESS);
 
427
 
 
428
    for (i=0; i<2; ++i) {
 
429
        pj_sockaddr_in addr;
 
430
 
 
431
        status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &g_server[i].sock);
 
432
        if (status != PJ_SUCCESS)
 
433
            return -10;
 
434
 
 
435
        pj_sockaddr_in_init(&addr, NULL, (pj_uint16_t)g_server[i].port);
 
436
 
 
437
        status = pj_sock_bind(g_server[i].sock, &addr, sizeof(addr));
 
438
        if (status != PJ_SUCCESS)
 
439
            return -20;
 
440
 
 
441
        status = pj_thread_create(pool, NULL, &server_thread, &g_server[i],
 
442
                                  0, 0, &g_server[i].thread);
 
443
        if (status != PJ_SUCCESS)
 
444
            return -30;
 
445
    }
 
446
 
 
447
    status = pj_timer_heap_create(pool, 16, &timer_heap);
 
448
    pj_assert(status == PJ_SUCCESS);
 
449
 
 
450
    status = pj_ioqueue_create(pool, 16, &ioqueue);
 
451
    pj_assert(status == PJ_SUCCESS);
 
452
 
 
453
    status = pj_dns_resolver_create(mem, NULL, 0, timer_heap, ioqueue, &resolver);
 
454
    if (status != PJ_SUCCESS)
 
455
        return -40;
 
456
 
 
457
    pj_dns_resolver_get_settings(resolver, &set);
 
458
    set.good_ns_ttl = 20;
 
459
    set.bad_ns_ttl = 20;
 
460
    pj_dns_resolver_set_settings(resolver, &set);
 
461
 
 
462
    status = pj_dns_resolver_set_ns(resolver, 2, nameservers, ports);
 
463
    pj_assert(status == PJ_SUCCESS);
 
464
 
 
465
    status = pj_thread_create(pool, NULL, &poll_worker_thread, NULL, 0, 0, &poll_thread);
 
466
    pj_assert(status == PJ_SUCCESS);
 
467
 
 
468
    return 0;
 
469
}
 
470
 
 
471
 
 
472
static void destroy(void)
 
473
{
 
474
    int i;
 
475
 
 
476
    thread_quit = PJ_TRUE;
 
477
 
 
478
    for (i=0; i<2; ++i) {
 
479
        pj_thread_join(g_server[i].thread);
 
480
        pj_sock_close(g_server[i].sock);
 
481
    }
 
482
 
 
483
    pj_thread_join(poll_thread);
 
484
 
 
485
    pj_dns_resolver_destroy(resolver, PJ_FALSE);
 
486
    pj_ioqueue_destroy(ioqueue);
 
487
    pj_timer_heap_destroy(timer_heap);
 
488
 
 
489
    pj_sem_destroy(sem);
 
490
    pj_pool_release(pool);
 
491
}
 
492
 
 
493
 
 
494
////////////////////////////////////////////////////////////////////////////
 
495
/* DNS A parser tests */
 
496
static int a_parser_test(void)
 
497
{
 
498
    pj_dns_parsed_packet pkt;
 
499
    pj_dns_a_record rec;
 
500
    pj_status_t rc;
 
501
 
 
502
    PJ_LOG(3,(THIS_FILE, "  DNS A record parser tests"));
 
503
 
 
504
    pkt.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
 
505
    pkt.ans = (pj_dns_parsed_rr*)
 
506
              pj_pool_calloc(pool, 32, sizeof(pj_dns_parsed_rr));
 
507
 
 
508
    /* Simple answer with direct A record, but with addition of
 
509
     * a CNAME and another A to confuse the parser.
 
510
     */
 
511
    PJ_LOG(3,(THIS_FILE, "    A RR with duplicate CNAME/A"));
 
512
    pkt.hdr.flags = 0;
 
513
    pkt.hdr.qdcount = 1;
 
514
    pkt.q[0].type = PJ_DNS_TYPE_A;
 
515
    pkt.q[0].dnsclass = 1;
 
516
    pkt.q[0].name = pj_str("ahost");
 
517
    pkt.hdr.anscount = 3;
 
518
 
 
519
    /* This is the RR corresponding to the query */
 
520
    pkt.ans[0].name = pj_str("ahost");
 
521
    pkt.ans[0].type = PJ_DNS_TYPE_A;
 
522
    pkt.ans[0].dnsclass = 1;
 
523
    pkt.ans[0].ttl = 1;
 
524
    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x01020304;
 
525
 
 
526
    /* CNAME to confuse the parser */
 
527
    pkt.ans[1].name = pj_str("ahost");
 
528
    pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
 
529
    pkt.ans[1].dnsclass = 1;
 
530
    pkt.ans[1].ttl = 1;
 
531
    pkt.ans[1].rdata.cname.name = pj_str("bhost");
 
532
 
 
533
    /* DNS A RR to confuse the parser */
 
534
    pkt.ans[2].name = pj_str("bhost");
 
535
    pkt.ans[2].type = PJ_DNS_TYPE_A;
 
536
    pkt.ans[2].dnsclass = 1;
 
537
    pkt.ans[2].ttl = 1;
 
538
    pkt.ans[2].rdata.a.ip_addr.s_addr = 0x0203;
 
539
 
 
540
 
 
541
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
542
    pj_assert(rc == PJ_SUCCESS);
 
543
    pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
 
544
    pj_assert(rec.alias.slen == 0);
 
545
    pj_assert(rec.addr_count == 1);
 
546
    pj_assert(rec.addr[0].s_addr == 0x01020304);
 
547
 
 
548
    /* Answer with the target corresponds to a CNAME entry, but not
 
549
     * as the first record, and with additions of some CNAME and A
 
550
     * entries to confuse the parser.
 
551
     */
 
552
    PJ_LOG(3,(THIS_FILE, "    CNAME RR with duplicate CNAME/A"));
 
553
    pkt.hdr.flags = 0;
 
554
    pkt.hdr.qdcount = 1;
 
555
    pkt.q[0].type = PJ_DNS_TYPE_A;
 
556
    pkt.q[0].dnsclass = 1;
 
557
    pkt.q[0].name = pj_str("ahost");
 
558
    pkt.hdr.anscount = 4;
 
559
 
 
560
    /* This is the DNS A record for the alias */
 
561
    pkt.ans[0].name = pj_str("ahostalias");
 
562
    pkt.ans[0].type = PJ_DNS_TYPE_A;
 
563
    pkt.ans[0].dnsclass = 1;
 
564
    pkt.ans[0].ttl = 1;
 
565
    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
 
566
 
 
567
    /* CNAME entry corresponding to the query */
 
568
    pkt.ans[1].name = pj_str("ahost");
 
569
    pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
 
570
    pkt.ans[1].dnsclass = 1;
 
571
    pkt.ans[1].ttl = 1;
 
572
    pkt.ans[1].rdata.cname.name = pj_str("ahostalias");
 
573
 
 
574
    /* Another CNAME to confuse the parser */
 
575
    pkt.ans[2].name = pj_str("ahost");
 
576
    pkt.ans[2].type = PJ_DNS_TYPE_CNAME;
 
577
    pkt.ans[2].dnsclass = 1;
 
578
    pkt.ans[2].ttl = 1;
 
579
    pkt.ans[2].rdata.cname.name = pj_str("ahostalias2");
 
580
 
 
581
    /* Another DNS A to confuse the parser */
 
582
    pkt.ans[3].name = pj_str("ahostalias2");
 
583
    pkt.ans[3].type = PJ_DNS_TYPE_A;
 
584
    pkt.ans[3].dnsclass = 1;
 
585
    pkt.ans[3].ttl = 1;
 
586
    pkt.ans[3].rdata.a.ip_addr.s_addr = 0x03030303;
 
587
 
 
588
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
589
    pj_assert(rc == PJ_SUCCESS);
 
590
    pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
 
591
    pj_assert(pj_strcmp2(&rec.alias, "ahostalias")==0);
 
592
    pj_assert(rec.addr_count == 1);
 
593
    pj_assert(rec.addr[0].s_addr == 0x02020202);
 
594
 
 
595
    /*
 
596
     * No query section.
 
597
     */
 
598
    PJ_LOG(3,(THIS_FILE, "    No query section"));
 
599
    pkt.hdr.qdcount = 0;
 
600
    pkt.hdr.anscount = 0;
 
601
 
 
602
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
603
    pj_assert(rc == PJLIB_UTIL_EDNSINANSWER);
 
604
 
 
605
    /*
 
606
     * No answer section.
 
607
     */
 
608
    PJ_LOG(3,(THIS_FILE, "    No answer section"));
 
609
    pkt.hdr.flags = 0;
 
610
    pkt.hdr.qdcount = 1;
 
611
    pkt.q[0].type = PJ_DNS_TYPE_A;
 
612
    pkt.q[0].dnsclass = 1;
 
613
    pkt.q[0].name = pj_str("ahost");
 
614
    pkt.hdr.anscount = 0;
 
615
 
 
616
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
617
    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
 
618
 
 
619
    /*
 
620
     * Answer doesn't match query.
 
621
     */
 
622
    PJ_LOG(3,(THIS_FILE, "    Answer doesn't match query"));
 
623
    pkt.hdr.flags = 0;
 
624
    pkt.hdr.qdcount = 1;
 
625
    pkt.q[0].type = PJ_DNS_TYPE_A;
 
626
    pkt.q[0].dnsclass = 1;
 
627
    pkt.q[0].name = pj_str("ahost");
 
628
    pkt.hdr.anscount = 1;
 
629
 
 
630
    /* An answer that doesn't match the query */
 
631
    pkt.ans[0].name = pj_str("ahostalias");
 
632
    pkt.ans[0].type = PJ_DNS_TYPE_A;
 
633
    pkt.ans[0].dnsclass = 1;
 
634
    pkt.ans[0].ttl = 1;
 
635
    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
 
636
 
 
637
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
638
    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
 
639
 
 
640
 
 
641
    /*
 
642
     * DNS CNAME that doesn't have corresponding DNS A.
 
643
     */
 
644
    PJ_LOG(3,(THIS_FILE, "    CNAME with no matching DNS A RR (1)"));
 
645
    pkt.hdr.flags = 0;
 
646
    pkt.hdr.qdcount = 1;
 
647
    pkt.q[0].type = PJ_DNS_TYPE_A;
 
648
    pkt.q[0].dnsclass = 1;
 
649
    pkt.q[0].name = pj_str("ahost");
 
650
    pkt.hdr.anscount = 1;
 
651
 
 
652
    /* The CNAME */
 
653
    pkt.ans[0].name = pj_str("ahost");
 
654
    pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
 
655
    pkt.ans[0].dnsclass = 1;
 
656
    pkt.ans[0].ttl = 1;
 
657
    pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
 
658
 
 
659
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
660
    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
 
661
 
 
662
 
 
663
    /*
 
664
     * DNS CNAME that doesn't have corresponding DNS A.
 
665
     */
 
666
    PJ_LOG(3,(THIS_FILE, "    CNAME with no matching DNS A RR (2)"));
 
667
    pkt.hdr.flags = 0;
 
668
    pkt.hdr.qdcount = 1;
 
669
    pkt.q[0].type = PJ_DNS_TYPE_A;
 
670
    pkt.q[0].dnsclass = 1;
 
671
    pkt.q[0].name = pj_str("ahost");
 
672
    pkt.hdr.anscount = 2;
 
673
 
 
674
    /* The CNAME */
 
675
    pkt.ans[0].name = pj_str("ahost");
 
676
    pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
 
677
    pkt.ans[0].dnsclass = 1;
 
678
    pkt.ans[0].ttl = 1;
 
679
    pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
 
680
 
 
681
    /* DNS A record, but the name doesn't match */
 
682
    pkt.ans[1].name = pj_str("ahost");
 
683
    pkt.ans[1].type = PJ_DNS_TYPE_A;
 
684
    pkt.ans[1].dnsclass = 1;
 
685
    pkt.ans[1].ttl = 1;
 
686
    pkt.ans[1].rdata.a.ip_addr.s_addr = 0x01020304;
 
687
 
 
688
    rc = pj_dns_parse_a_response(&pkt, &rec);
 
689
    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
 
690
 
 
691
    return 0;
 
692
}
 
693
 
 
694
 
 
695
////////////////////////////////////////////////////////////////////////////
 
696
/* Simple DNS test */
 
697
#define IP_ADDR0    0x00010203
 
698
 
 
699
static void dns_callback(void *user_data,
 
700
                         pj_status_t status,
 
701
                         pj_dns_parsed_packet *resp)
 
702
{
 
703
    PJ_UNUSED_ARG(user_data);
 
704
 
 
705
    pj_sem_post(sem);
 
706
 
 
707
    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
 
708
    PJ_ASSERT_ON_FAIL(resp, return);
 
709
    PJ_ASSERT_ON_FAIL(resp->hdr.anscount == 1, return);
 
710
    PJ_ASSERT_ON_FAIL(resp->ans[0].type == PJ_DNS_TYPE_A, return);
 
711
    PJ_ASSERT_ON_FAIL(resp->ans[0].rdata.a.ip_addr.s_addr == IP_ADDR0, return);
 
712
 
 
713
}
 
714
 
 
715
 
 
716
static int simple_test(void)
 
717
{
 
718
    pj_str_t name = pj_str("helloworld");
 
719
    pj_dns_parsed_packet *r;
 
720
    pj_status_t status;
 
721
 
 
722
    PJ_LOG(3,(THIS_FILE, "  simple successful test"));
 
723
 
 
724
    g_server[0].pkt_count = 0;
 
725
    g_server[1].pkt_count = 0;
 
726
 
 
727
    g_server[0].action = ACTION_REPLY;
 
728
    r = &g_server[0].resp;
 
729
    r->hdr.qdcount = 1;
 
730
    r->hdr.anscount = 1;
 
731
    r->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
 
732
    r->q[0].type = PJ_DNS_TYPE_A;
 
733
    r->q[0].dnsclass = 1;
 
734
    r->q[0].name = name;
 
735
    r->ans = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_rr);
 
736
    r->ans[0].type = PJ_DNS_TYPE_A;
 
737
    r->ans[0].dnsclass = 1;
 
738
    r->ans[0].name = name;
 
739
    r->ans[0].rdata.a.ip_addr.s_addr = IP_ADDR0;
 
740
 
 
741
    g_server[1].action = ACTION_REPLY;
 
742
    r = &g_server[1].resp;
 
743
    r->hdr.qdcount = 1;
 
744
    r->hdr.anscount = 1;
 
745
    r->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
 
746
    r->q[0].type = PJ_DNS_TYPE_A;
 
747
    r->q[0].dnsclass = 1;
 
748
    r->q[0].name = name;
 
749
    r->ans = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_rr);
 
750
    r->ans[0].type = PJ_DNS_TYPE_A;
 
751
    r->ans[0].dnsclass = 1;
 
752
    r->ans[0].name = name;
 
753
    r->ans[0].rdata.a.ip_addr.s_addr = IP_ADDR0;
 
754
 
 
755
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
756
                                         &dns_callback, NULL, NULL);
 
757
    if (status != PJ_SUCCESS)
 
758
        return -1000;
 
759
 
 
760
    pj_sem_wait(sem);
 
761
    pj_thread_sleep(1000);
 
762
 
 
763
 
 
764
    /* Both servers must get packet */
 
765
    pj_assert(g_server[0].pkt_count == 1);
 
766
    pj_assert(g_server[1].pkt_count == 1);
 
767
 
 
768
    return 0;
 
769
}
 
770
 
 
771
 
 
772
////////////////////////////////////////////////////////////////////////////
 
773
/* DNS nameserver fail-over test */
 
774
 
 
775
static void dns_callback_1b(void *user_data,
 
776
                            pj_status_t status,
 
777
                            pj_dns_parsed_packet *resp)
 
778
{
 
779
    PJ_UNUSED_ARG(user_data);
 
780
    PJ_UNUSED_ARG(resp);
 
781
 
 
782
    pj_sem_post(sem);
 
783
 
 
784
    PJ_ASSERT_ON_FAIL(status==PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_RCODE_NXDOMAIN),
 
785
                      return);
 
786
}
 
787
 
 
788
 
 
789
 
 
790
 
 
791
/* DNS test */
 
792
static int dns_test(void)
 
793
{
 
794
    pj_str_t name = pj_str("name00");
 
795
    pj_status_t status;
 
796
 
 
797
    PJ_LOG(3,(THIS_FILE, "  simple error response test"));
 
798
 
 
799
    g_server[0].pkt_count = 0;
 
800
    g_server[1].pkt_count = 0;
 
801
 
 
802
    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
 
803
    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
 
804
 
 
805
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
806
                                         &dns_callback_1b, NULL, NULL);
 
807
    if (status != PJ_SUCCESS)
 
808
        return -1000;
 
809
 
 
810
    pj_sem_wait(sem);
 
811
    pj_thread_sleep(1000);
 
812
 
 
813
    /* Now only server 0 should get packet, since both servers are
 
814
     * in STATE_ACTIVE state
 
815
     */
 
816
    pj_assert((g_server[0].pkt_count == 1 && g_server[1].pkt_count == 0) ||
 
817
              (g_server[1].pkt_count == 1 && g_server[0].pkt_count == 0));
 
818
 
 
819
    /* Wait to allow probing period to complete */
 
820
    PJ_LOG(3,(THIS_FILE, "  waiting for active NS to expire (%d sec)",
 
821
                         set.good_ns_ttl));
 
822
    pj_thread_sleep(set.good_ns_ttl * 1000);
 
823
 
 
824
    /* 
 
825
     * Fail-over test 
 
826
     */
 
827
    PJ_LOG(3,(THIS_FILE, "  failing server0"));
 
828
    g_server[0].action = ACTION_IGNORE;
 
829
    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
 
830
 
 
831
    g_server[0].pkt_count = 0;
 
832
    g_server[1].pkt_count = 0;
 
833
 
 
834
    name = pj_str("name01");
 
835
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
836
                                         &dns_callback_1b, NULL, NULL);
 
837
    if (status != PJ_SUCCESS)
 
838
        return -1000;
 
839
 
 
840
    pj_sem_wait(sem);
 
841
 
 
842
    /*
 
843
     * Check that both servers still receive requests, since they are
 
844
     * in probing state.
 
845
     */
 
846
    PJ_LOG(3,(THIS_FILE, "  checking both NS during probing period"));
 
847
    g_server[0].action = ACTION_IGNORE;
 
848
    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
 
849
 
 
850
    g_server[0].pkt_count = 0;
 
851
    g_server[1].pkt_count = 0;
 
852
 
 
853
    name = pj_str("name02");
 
854
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
855
                                         &dns_callback_1b, NULL, NULL);
 
856
    if (status != PJ_SUCCESS)
 
857
        return -1000;
 
858
 
 
859
    pj_sem_wait(sem);
 
860
    pj_thread_sleep(set.qretr_delay *  set.qretr_count);
 
861
 
 
862
    /* Both servers must get requests */
 
863
    pj_assert(g_server[0].pkt_count >= 1);
 
864
    pj_assert(g_server[1].pkt_count == 1);
 
865
 
 
866
    /* Wait to allow probing period to complete */
 
867
    PJ_LOG(3,(THIS_FILE, "  waiting for probing state to end (%d sec)",
 
868
                         set.qretr_delay * 
 
869
                         (set.qretr_count+2) / 1000));
 
870
    pj_thread_sleep(set.qretr_delay * (set.qretr_count + 2));
 
871
 
 
872
 
 
873
    /*
 
874
     * Now only server 1 should get requests.
 
875
     */
 
876
    PJ_LOG(3,(THIS_FILE, "  verifying only good NS is used"));
 
877
    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
 
878
    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
 
879
 
 
880
    g_server[0].pkt_count = 0;
 
881
    g_server[1].pkt_count = 0;
 
882
 
 
883
    name = pj_str("name03");
 
884
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
885
                                         &dns_callback_1b, NULL, NULL);
 
886
    if (status != PJ_SUCCESS)
 
887
        return -1000;
 
888
 
 
889
    pj_sem_wait(sem);
 
890
    pj_thread_sleep(1000);
 
891
 
 
892
    /* Both servers must get requests */
 
893
    pj_assert(g_server[0].pkt_count == 0);
 
894
    pj_assert(g_server[1].pkt_count == 1);
 
895
 
 
896
    /* Wait to allow probing period to complete */
 
897
    PJ_LOG(3,(THIS_FILE, "  waiting for active NS to expire (%d sec)",
 
898
                         set.good_ns_ttl));
 
899
    pj_thread_sleep(set.good_ns_ttl * 1000);
 
900
 
 
901
    /*
 
902
     * Now fail server 1 to switch to server 0
 
903
     */
 
904
    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
 
905
    g_server[1].action = ACTION_IGNORE;
 
906
 
 
907
    g_server[0].pkt_count = 0;
 
908
    g_server[1].pkt_count = 0;
 
909
 
 
910
    name = pj_str("name04");
 
911
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
912
                                         &dns_callback_1b, NULL, NULL);
 
913
    if (status != PJ_SUCCESS)
 
914
        return -1000;
 
915
 
 
916
    pj_sem_wait(sem);
 
917
 
 
918
    /* Wait to allow probing period to complete */
 
919
    PJ_LOG(3,(THIS_FILE, "  waiting for probing state (%d sec)",
 
920
                         set.qretr_delay * (set.qretr_count+2) / 1000));
 
921
    pj_thread_sleep(set.qretr_delay * (set.qretr_count + 2));
 
922
 
 
923
    /*
 
924
     * Now only server 0 should get requests.
 
925
     */
 
926
    PJ_LOG(3,(THIS_FILE, "  verifying good NS"));
 
927
    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
 
928
    g_server[1].action = ACTION_IGNORE;
 
929
 
 
930
    g_server[0].pkt_count = 0;
 
931
    g_server[1].pkt_count = 0;
 
932
 
 
933
    name = pj_str("name05");
 
934
    status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
 
935
                                         &dns_callback_1b, NULL, NULL);
 
936
    if (status != PJ_SUCCESS)
 
937
        return -1000;
 
938
 
 
939
    pj_sem_wait(sem);
 
940
    pj_thread_sleep(1000);
 
941
 
 
942
    /* Only good NS should get request */
 
943
    pj_assert(g_server[0].pkt_count == 1);
 
944
    pj_assert(g_server[1].pkt_count == 0);
 
945
 
 
946
 
 
947
    return 0;
 
948
}
 
949
 
 
950
 
 
951
////////////////////////////////////////////////////////////////////////////
 
952
/* Resolver test, normal, with CNAME */
 
953
#define IP_ADDR1    0x02030405
 
954
#define PORT1       50061
 
955
 
 
956
static void action1_1(const pj_dns_parsed_packet *pkt,
 
957
                      pj_dns_parsed_packet **p_res)
 
958
{
 
959
    pj_dns_parsed_packet *res;
 
960
    char *target = "sip.somedomain.com";
 
961
 
 
962
    res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
 
963
 
 
964
    if (res->q == NULL) {
 
965
        res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
 
966
    }
 
967
    if (res->ans == NULL) {
 
968
        res->ans = (pj_dns_parsed_rr*) 
 
969
                  pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr));
 
970
    }
 
971
 
 
972
    res->hdr.qdcount = 1;
 
973
    res->q[0].type = pkt->q[0].type;
 
974
    res->q[0].dnsclass = pkt->q[0].dnsclass;
 
975
    res->q[0].name = pkt->q[0].name;
 
976
 
 
977
    if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
 
978
 
 
979
        pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp.somedomain.com")==0);
 
980
 
 
981
        res->hdr.anscount = 1;
 
982
        res->ans[0].type = PJ_DNS_TYPE_SRV;
 
983
        res->ans[0].dnsclass = 1;
 
984
        res->ans[0].name = res->q[0].name;
 
985
        res->ans[0].ttl = 1;
 
986
        res->ans[0].rdata.srv.prio = 1;
 
987
        res->ans[0].rdata.srv.weight = 2;
 
988
        res->ans[0].rdata.srv.port = PORT1;
 
989
        res->ans[0].rdata.srv.target = pj_str(target);
 
990
 
 
991
    } else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
 
992
        char *alias = "sipalias.somedomain.com";
 
993
 
 
994
        pj_assert(pj_strcmp2(&res->q[0].name, target)==0);
 
995
 
 
996
        res->hdr.anscount = 2;
 
997
        res->ans[0].type = PJ_DNS_TYPE_CNAME;
 
998
        res->ans[0].dnsclass = 1;
 
999
        res->ans[0].ttl = 1000; /* resolver should select minimum TTL */
 
1000
        res->ans[0].name = res->q[0].name;
 
1001
        res->ans[0].rdata.cname.name = pj_str(alias);
 
1002
 
 
1003
        res->ans[1].type = PJ_DNS_TYPE_A;
 
1004
        res->ans[1].dnsclass = 1;
 
1005
        res->ans[1].ttl = 1;
 
1006
        res->ans[1].name = pj_str(alias);
 
1007
        res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR1;
 
1008
    }
 
1009
 
 
1010
    *p_res = res;
 
1011
}
 
1012
 
 
1013
static void srv_cb_1(void *user_data,
 
1014
                     pj_status_t status,
 
1015
                     const pj_dns_srv_record *rec)
 
1016
{
 
1017
    PJ_UNUSED_ARG(user_data);
 
1018
 
 
1019
    pj_sem_post(sem);
 
1020
 
 
1021
    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
 
1022
    PJ_ASSERT_ON_FAIL(rec->count == 1, return);
 
1023
    PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return);
 
1024
    PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return);
 
1025
    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0,
 
1026
                      return);
 
1027
    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0,
 
1028
                      return);
 
1029
    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR1, return);
 
1030
    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return);
 
1031
 
 
1032
    
 
1033
}
 
1034
 
 
1035
static void srv_cb_1b(void *user_data,
 
1036
                      pj_status_t status,
 
1037
                      const pj_dns_srv_record *rec)
 
1038
{
 
1039
    PJ_UNUSED_ARG(user_data);
 
1040
 
 
1041
    pj_sem_post(sem);
 
1042
 
 
1043
    PJ_ASSERT_ON_FAIL(status==PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_RCODE_NXDOMAIN),
 
1044
                      return);
 
1045
    PJ_ASSERT_ON_FAIL(rec->count == 0, return);
 
1046
}
 
1047
 
 
1048
static int srv_resolver_test(void)
 
1049
{
 
1050
    pj_status_t status;
 
1051
    pj_str_t domain = pj_str("somedomain.com");
 
1052
    pj_str_t res_name = pj_str("_sip._udp.");
 
1053
 
 
1054
    /* Successful scenario */
 
1055
    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): success scenario"));
 
1056
 
 
1057
    g_server[0].action = ACTION_CB;
 
1058
    g_server[0].action_cb = &action1_1;
 
1059
    g_server[1].action = ACTION_CB;
 
1060
    g_server[1].action_cb = &action1_1;
 
1061
 
 
1062
    g_server[0].pkt_count = 0;
 
1063
    g_server[1].pkt_count = 0;
 
1064
 
 
1065
    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
 
1066
                                NULL, &srv_cb_1, NULL);
 
1067
    pj_assert(status == PJ_SUCCESS);
 
1068
 
 
1069
    pj_sem_wait(sem);
 
1070
 
 
1071
    /* Because of previous tests, only NS 1 should get the request */
 
1072
    pj_assert(g_server[0].pkt_count == 2);  /* 2 because of SRV and A resolution */
 
1073
    pj_assert(g_server[1].pkt_count == 0);
 
1074
 
 
1075
 
 
1076
    /* Wait until cache expires and nameserver state moves out from STATE_PROBING */
 
1077
    PJ_LOG(3,(THIS_FILE, "  waiting for cache to expire (~15 secs).."));
 
1078
    pj_thread_sleep(1000 + 
 
1079
                    ((set.qretr_count + 2) * set.qretr_delay));
 
1080
 
 
1081
    /* Successful scenario */
 
1082
    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): parallel queries"));
 
1083
    g_server[0].pkt_count = 0;
 
1084
    g_server[1].pkt_count = 0;
 
1085
 
 
1086
    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
 
1087
                                NULL, &srv_cb_1, NULL);
 
1088
    pj_assert(status == PJ_SUCCESS);
 
1089
 
 
1090
 
 
1091
    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
 
1092
                                NULL, &srv_cb_1, NULL);
 
1093
    pj_assert(status == PJ_SUCCESS);
 
1094
 
 
1095
    pj_sem_wait(sem);
 
1096
    pj_sem_wait(sem);
 
1097
 
 
1098
    /* Only server one should get a query */
 
1099
    pj_assert(g_server[0].pkt_count == 2);  /* 2 because of SRV and A resolution */
 
1100
    pj_assert(g_server[1].pkt_count == 0);
 
1101
 
 
1102
    /* Since TTL is one, subsequent queries should fail */
 
1103
    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): cache expires scenario"));
 
1104
 
 
1105
 
 
1106
    pj_thread_sleep(1000);
 
1107
 
 
1108
    g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
 
1109
    g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
 
1110
 
 
1111
    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
 
1112
                                NULL, &srv_cb_1b, NULL);
 
1113
    pj_assert(status == PJ_SUCCESS);
 
1114
 
 
1115
    pj_sem_wait(sem);
 
1116
 
 
1117
    return 0;
 
1118
}
 
1119
 
 
1120
 
 
1121
////////////////////////////////////////////////////////////////////////////
 
1122
/* Fallback because there's no SRV in answer */
 
1123
#define TARGET      "domain2.com"
 
1124
#define IP_ADDR2    0x02030405
 
1125
#define PORT2       50062
 
1126
 
 
1127
static void action2_1(const pj_dns_parsed_packet *pkt,
 
1128
                      pj_dns_parsed_packet **p_res)
 
1129
{
 
1130
    pj_dns_parsed_packet *res;
 
1131
 
 
1132
    res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
 
1133
 
 
1134
    res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
 
1135
    res->ans = (pj_dns_parsed_rr*) 
 
1136
               pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr));
 
1137
 
 
1138
    res->hdr.qdcount = 1;
 
1139
    res->q[0].type = pkt->q[0].type;
 
1140
    res->q[0].dnsclass = pkt->q[0].dnsclass;
 
1141
    res->q[0].name = pkt->q[0].name;
 
1142
 
 
1143
    if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
 
1144
 
 
1145
        pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." TARGET)==0);
 
1146
 
 
1147
        res->hdr.anscount = 1;
 
1148
        res->ans[0].type = PJ_DNS_TYPE_A;    // <-- this will cause the fallback
 
1149
        res->ans[0].dnsclass = 1;
 
1150
        res->ans[0].name = res->q[0].name;
 
1151
        res->ans[0].ttl = 1;
 
1152
        res->ans[0].rdata.srv.prio = 1;
 
1153
        res->ans[0].rdata.srv.weight = 2;
 
1154
        res->ans[0].rdata.srv.port = PORT2;
 
1155
        res->ans[0].rdata.srv.target = pj_str("sip01." TARGET);
 
1156
 
 
1157
    } else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
 
1158
        char *alias = "sipalias01." TARGET;
 
1159
 
 
1160
        pj_assert(pj_strcmp2(&res->q[0].name, TARGET)==0);
 
1161
 
 
1162
        res->hdr.anscount = 2;
 
1163
        res->ans[0].type = PJ_DNS_TYPE_CNAME;
 
1164
        res->ans[0].dnsclass = 1;
 
1165
        res->ans[0].name = res->q[0].name;
 
1166
        res->ans[0].ttl = 1;
 
1167
        res->ans[0].rdata.cname.name = pj_str(alias);
 
1168
 
 
1169
        res->ans[1].type = PJ_DNS_TYPE_A;
 
1170
        res->ans[1].dnsclass = 1;
 
1171
        res->ans[1].name = pj_str(alias);
 
1172
        res->ans[1].ttl = 1;
 
1173
        res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR2;
 
1174
    }
 
1175
 
 
1176
    *p_res = res;
 
1177
}
 
1178
 
 
1179
static void srv_cb_2(void *user_data,
 
1180
                     pj_status_t status,
 
1181
                     const pj_dns_srv_record *rec)
 
1182
{
 
1183
    PJ_UNUSED_ARG(user_data);
 
1184
 
 
1185
    pj_sem_post(sem);
 
1186
 
 
1187
    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
 
1188
    PJ_ASSERT_ON_FAIL(rec->count == 1, return);
 
1189
    PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 0, return);
 
1190
    PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 0, return);
 
1191
    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0,
 
1192
                      return);
 
1193
    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0,
 
1194
                      return);
 
1195
    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR2, return);
 
1196
    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT2, return);
 
1197
}
 
1198
 
 
1199
static int srv_resolver_fallback_test(void)
 
1200
{
 
1201
    pj_status_t status;
 
1202
    pj_str_t domain = pj_str(TARGET);
 
1203
    pj_str_t res_name = pj_str("_sip._udp.");
 
1204
 
 
1205
    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): fallback test"));
 
1206
 
 
1207
    g_server[0].action = ACTION_CB;
 
1208
    g_server[0].action_cb = &action2_1;
 
1209
    g_server[1].action = ACTION_CB;
 
1210
    g_server[1].action_cb = &action2_1;
 
1211
 
 
1212
    status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE,
 
1213
                                NULL, &srv_cb_2, NULL);
 
1214
    if (status != PJ_SUCCESS) {
 
1215
        app_perror("   srv_resolve error", status);
 
1216
        pj_assert(status == PJ_SUCCESS);
 
1217
    }
 
1218
 
 
1219
    pj_sem_wait(sem);
 
1220
 
 
1221
    /* Subsequent query should just get the response from the cache */
 
1222
    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): cache test"));
 
1223
    g_server[0].pkt_count = 0;
 
1224
    g_server[1].pkt_count = 0;
 
1225
 
 
1226
    status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE,
 
1227
                                NULL, &srv_cb_2, NULL);
 
1228
    if (status != PJ_SUCCESS) {
 
1229
        app_perror("   srv_resolve error", status);
 
1230
        pj_assert(status == PJ_SUCCESS);
 
1231
    }
 
1232
 
 
1233
    pj_sem_wait(sem);
 
1234
 
 
1235
    pj_assert(g_server[0].pkt_count == 0);
 
1236
    pj_assert(g_server[1].pkt_count == 0);
 
1237
 
 
1238
    return 0;
 
1239
}
 
1240
 
 
1241
 
 
1242
////////////////////////////////////////////////////////////////////////////
 
1243
/* Too many SRV or A entries */
 
1244
#define DOMAIN3     "d3"
 
1245
#define SRV_COUNT3  (PJ_DNS_SRV_MAX_ADDR+1)
 
1246
#define A_COUNT3    (PJ_DNS_MAX_IP_IN_A_REC+1)
 
1247
#define PORT3       50063
 
1248
#define IP_ADDR3    0x03030303
 
1249
 
 
1250
static void action3_1(const pj_dns_parsed_packet *pkt,
 
1251
                      pj_dns_parsed_packet **p_res)
 
1252
{
 
1253
    pj_dns_parsed_packet *res;
 
1254
    unsigned i;
 
1255
 
 
1256
    res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
 
1257
 
 
1258
    if (res->q == NULL) {
 
1259
        res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
 
1260
    }
 
1261
 
 
1262
    res->hdr.qdcount = 1;
 
1263
    res->q[0].type = pkt->q[0].type;
 
1264
    res->q[0].dnsclass = pkt->q[0].dnsclass;
 
1265
    res->q[0].name = pkt->q[0].name;
 
1266
 
 
1267
    if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
 
1268
 
 
1269
        pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." DOMAIN3)==0);
 
1270
 
 
1271
        res->hdr.anscount = SRV_COUNT3;
 
1272
        res->ans = (pj_dns_parsed_rr*) 
 
1273
                   pj_pool_calloc(pool, SRV_COUNT3, sizeof(pj_dns_parsed_rr));
 
1274
 
 
1275
        for (i=0; i<SRV_COUNT3; ++i) {
 
1276
            char *target;
 
1277
 
 
1278
            res->ans[i].type = PJ_DNS_TYPE_SRV;
 
1279
            res->ans[i].dnsclass = 1;
 
1280
            res->ans[i].name = res->q[0].name;
 
1281
            res->ans[i].ttl = 1;
 
1282
            res->ans[i].rdata.srv.prio = (pj_uint16_t)i;
 
1283
            res->ans[i].rdata.srv.weight = 2;
 
1284
            res->ans[i].rdata.srv.port = (pj_uint16_t)(PORT3+i);
 
1285
 
 
1286
            target = (char*)pj_pool_alloc(pool, 16);
 
1287
            sprintf(target, "sip%02d." DOMAIN3, i);
 
1288
            res->ans[i].rdata.srv.target = pj_str(target);
 
1289
        }
 
1290
 
 
1291
    } else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
 
1292
 
 
1293
        //pj_assert(pj_strcmp2(&res->q[0].name, "sip." DOMAIN3)==0);
 
1294
 
 
1295
        res->hdr.anscount = A_COUNT3;
 
1296
        res->ans = (pj_dns_parsed_rr*) 
 
1297
                   pj_pool_calloc(pool, A_COUNT3, sizeof(pj_dns_parsed_rr));
 
1298
 
 
1299
        for (i=0; i<A_COUNT3; ++i) {
 
1300
            res->ans[i].type = PJ_DNS_TYPE_A;
 
1301
            res->ans[i].dnsclass = 1;
 
1302
            res->ans[i].ttl = 1;
 
1303
            res->ans[i].name = res->q[0].name;
 
1304
            res->ans[i].rdata.a.ip_addr.s_addr = IP_ADDR3+i;
 
1305
        }
 
1306
    }
 
1307
 
 
1308
    *p_res = res;
 
1309
}
 
1310
 
 
1311
static void srv_cb_3(void *user_data,
 
1312
                     pj_status_t status,
 
1313
                     const pj_dns_srv_record *rec)
 
1314
{
 
1315
    unsigned i;
 
1316
 
 
1317
    PJ_UNUSED_ARG(user_data);
 
1318
    PJ_UNUSED_ARG(status);
 
1319
    PJ_UNUSED_ARG(rec);
 
1320
 
 
1321
    pj_assert(status == PJ_SUCCESS);
 
1322
    pj_assert(rec->count == PJ_DNS_SRV_MAX_ADDR);
 
1323
 
 
1324
    for (i=0; i<PJ_DNS_SRV_MAX_ADDR; ++i) {
 
1325
        unsigned j;
 
1326
 
 
1327
        pj_assert(rec->entry[i].priority == i);
 
1328
        pj_assert(rec->entry[i].weight == 2);
 
1329
        //pj_assert(pj_strcmp2(&rec->entry[i].server.name, "sip." DOMAIN3)==0);
 
1330
        pj_assert(rec->entry[i].server.alias.slen == 0);
 
1331
        pj_assert(rec->entry[i].port == PORT3+i);
 
1332
 
 
1333
        pj_assert(rec->entry[i].server.addr_count == PJ_DNS_MAX_IP_IN_A_REC);
 
1334
 
 
1335
        for (j=0; j<PJ_DNS_MAX_IP_IN_A_REC; ++j) {
 
1336
            pj_assert(rec->entry[i].server.addr[j].s_addr == IP_ADDR3+j);
 
1337
        }
 
1338
    }
 
1339
 
 
1340
    pj_sem_post(sem);
 
1341
}
 
1342
 
 
1343
static int srv_resolver_many_test(void)
 
1344
{
 
1345
    pj_status_t status;
 
1346
    pj_str_t domain = pj_str(DOMAIN3);
 
1347
    pj_str_t res_name = pj_str("_sip._udp.");
 
1348
 
 
1349
    /* Successful scenario */
 
1350
    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): too many entries test"));
 
1351
 
 
1352
    g_server[0].action = ACTION_CB;
 
1353
    g_server[0].action_cb = &action3_1;
 
1354
    g_server[1].action = ACTION_CB;
 
1355
    g_server[1].action_cb = &action3_1;
 
1356
 
 
1357
    g_server[0].pkt_count = 0;
 
1358
    g_server[1].pkt_count = 0;
 
1359
 
 
1360
    status = pj_dns_srv_resolve(&domain, &res_name, 1, pool, resolver, PJ_TRUE,
 
1361
                                NULL, &srv_cb_3, NULL);
 
1362
    pj_assert(status == PJ_SUCCESS);
 
1363
 
 
1364
    pj_sem_wait(sem);
 
1365
 
 
1366
    return 0;
 
1367
}
 
1368
 
 
1369
 
 
1370
////////////////////////////////////////////////////////////////////////////
 
1371
 
 
1372
 
 
1373
int resolver_test(void)
 
1374
{
 
1375
    int rc;
 
1376
    
 
1377
    rc = init();
 
1378
    if (rc != 0)
 
1379
        goto on_error;
 
1380
 
 
1381
    rc = a_parser_test();
 
1382
    if (rc != 0)
 
1383
        goto on_error;
 
1384
 
 
1385
    rc = simple_test();
 
1386
    if (rc != 0)
 
1387
        goto on_error;
 
1388
 
 
1389
    rc = dns_test();
 
1390
    if (rc != 0)
 
1391
        goto on_error;
 
1392
 
 
1393
    srv_resolver_test();
 
1394
    srv_resolver_fallback_test();
 
1395
    srv_resolver_many_test();
 
1396
 
 
1397
    destroy();
 
1398
    return 0;
 
1399
 
 
1400
on_error:
 
1401
    destroy();
 
1402
    return rc;
 
1403
}
 
1404
 
 
1405