blob: a9ffec01804b4ae5a218103d809bd4a669684e3b [file] [log] [blame]
Benny Prijonofa9e5b12006-10-08 12:39:34 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
Benny Prijono32177c02008-06-20 22:44:47 +00004 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonofa9e5b12006-10-08 12:39:34 +00005 *
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 "test.h"
21#include <pjsip.h>
22#include <pjlib.h>
23#include <pjlib-util.h>
24
25/* For logging purpose. */
26#define THIS_FILE "dns_test.c"
27
28struct result
29{
30 pj_status_t status;
31 pjsip_server_addresses servers;
32};
33
34
35static void cb(pj_status_t status,
36 void *token,
37 const struct pjsip_server_addresses *addr)
38{
Benny Prijonoa1e69682007-05-11 15:14:34 +000039 struct result *result = (struct result*) token;
Benny Prijonofa9e5b12006-10-08 12:39:34 +000040
41 result->status = status;
42 if (status == PJ_SUCCESS)
43 pj_memcpy(&result->servers, addr, sizeof(*addr));
44}
45
46
47static void add_dns_entries(pj_dns_resolver *resv)
48{
49 /* Inject DNS SRV entry */
50 pj_dns_parsed_packet pkt;
Benny Prijonod4791af2007-06-19 08:46:02 +000051 pj_dns_parsed_query q;
Benny Prijonofa9e5b12006-10-08 12:39:34 +000052 pj_dns_parsed_rr ans[4];
53 pj_dns_parsed_rr ar[5];
Benny Prijono91475442007-03-03 02:13:55 +000054 pj_str_t tmp;
Benny Prijonofa9e5b12006-10-08 12:39:34 +000055 unsigned i;
56
57 /*
58 * This is answer to SRV query to "example.com" domain, and
59 * the answer contains full reference to the A records of
60 * the server. The full DNS records is :
61
62 _sip._udp.example.com 3600 IN SRV 0 0 5060 sip01.example.com.
63 _sip._udp.example.com 3600 IN SRV 0 20 5060 sip02.example.com.
64 _sip._udp.example.com 3600 IN SRV 0 10 5060 sip03.example.com.
65 _sip._udp.example.com 3600 IN SRV 1 0 5060 sip04.example.com.
66
67 sip01.example.com. 3600 IN A 1.1.1.1
68 sip02.example.com. 3600 IN A 2.2.2.2
69 sip03.example.com. 3600 IN A 3.3.3.3
70 sip04.example.com. 3600 IN A 4.4.4.4
71
72 ; Additionally, add A record for "example.com"
73 example.com. 3600 IN A 5.5.5.5
74
75 */
76 pj_bzero(&pkt, sizeof(pkt));
77 pj_bzero(ans, sizeof(ans));
78 pj_bzero(ar, sizeof(ar));
79
80 pkt.hdr.flags = PJ_DNS_SET_QR(1);
81 pkt.hdr.anscount = PJ_ARRAY_SIZE(ans);
82 pkt.hdr.arcount = 0;
83 pkt.ans = ans;
84 pkt.arr = ar;
85
86 ans[0].name = pj_str("_sip._udp.example.com");
87 ans[0].type = PJ_DNS_TYPE_SRV;
88 ans[0].dnsclass = PJ_DNS_CLASS_IN;
89 ans[0].ttl = 3600;
90 ans[0].rdata.srv.prio = 0;
91 ans[0].rdata.srv.weight = 0;
92 ans[0].rdata.srv.port = 5060;
93 ans[0].rdata.srv.target = pj_str("sip01.example.com");
94
95 ans[1].name = pj_str("_sip._udp.example.com");
96 ans[1].type = PJ_DNS_TYPE_SRV;
97 ans[1].dnsclass = PJ_DNS_CLASS_IN;
98 ans[1].ttl = 3600;
99 ans[1].rdata.srv.prio = 0;
100 ans[1].rdata.srv.weight = 20;
101 ans[1].rdata.srv.port = 5060;
102 ans[1].rdata.srv.target = pj_str("sip02.example.com");
103
104 ans[2].name = pj_str("_sip._udp.example.com");
105 ans[2].type = PJ_DNS_TYPE_SRV;
106 ans[2].dnsclass = PJ_DNS_CLASS_IN;
107 ans[2].ttl = 3600;
108 ans[2].rdata.srv.prio = 0;
109 ans[2].rdata.srv.weight = 10;
110 ans[2].rdata.srv.port = 5060;
111 ans[2].rdata.srv.target = pj_str("sip03.example.com");
112
113 ans[3].name = pj_str("_sip._udp.example.com");
114 ans[3].type = PJ_DNS_TYPE_SRV;
115 ans[3].dnsclass = PJ_DNS_CLASS_IN;
116 ans[3].ttl = 3600;
117 ans[3].rdata.srv.prio = 1;
118 ans[3].rdata.srv.weight = 0;
119 ans[3].rdata.srv.port = 5060;
120 ans[3].rdata.srv.target = pj_str("sip04.example.com");
121
122 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
123
124 ar[0].name = pj_str("sip01.example.com");
125 ar[0].type = PJ_DNS_TYPE_A;
126 ar[0].dnsclass = PJ_DNS_CLASS_IN;
127 ar[0].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000128 ar[0].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "1.1.1.1"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000129
130 ar[1].name = pj_str("sip02.example.com");
131 ar[1].type = PJ_DNS_TYPE_A;
132 ar[1].dnsclass = PJ_DNS_CLASS_IN;
133 ar[1].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000134 ar[1].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "2.2.2.2"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000135
136 ar[2].name = pj_str("sip03.example.com");
137 ar[2].type = PJ_DNS_TYPE_A;
138 ar[2].dnsclass = PJ_DNS_CLASS_IN;
139 ar[2].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000140 ar[2].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "3.3.3.3"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000141
142 ar[3].name = pj_str("sip04.example.com");
143 ar[3].type = PJ_DNS_TYPE_A;
144 ar[3].dnsclass = PJ_DNS_CLASS_IN;
145 ar[3].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000146 ar[3].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "4.4.4.4"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000147
148 ar[4].name = pj_str("example.com");
149 ar[4].type = PJ_DNS_TYPE_A;
150 ar[4].dnsclass = PJ_DNS_CLASS_IN;
151 ar[4].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000152 ar[4].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "5.5.5.5"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000153
154 /*
155 * Create individual A records for all hosts in "example.com" domain.
156 */
157 for (i=0; i<PJ_ARRAY_SIZE(ar); ++i) {
158 pj_bzero(&pkt, sizeof(pkt));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000159 pkt.hdr.flags = PJ_DNS_SET_QR(1);
Benny Prijonod4791af2007-06-19 08:46:02 +0000160 pkt.hdr.qdcount = 1;
161 pkt.q = &q;
162 q.name = ar[i].name;
163 q.type = ar[i].type;
164 q.dnsclass = PJ_DNS_CLASS_IN;
165 pkt.hdr.anscount = 1;
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000166 pkt.ans = &ar[i];
167
168 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
169 }
170
171 /*
172 * Simulate DNS error response by creating these answers.
173 * Sample of invalid SRV records: _sip._udp.sip01.example.com.
174 */
175 for (i=0; i<PJ_ARRAY_SIZE(ans); ++i) {
176 pj_dns_parsed_query q;
177 char buf[128];
178 char *services[] = { "_sip._udp.", "_sip._tcp.", "_sips._tcp."};
179 unsigned j;
180
181 for (j=0; j<PJ_ARRAY_SIZE(services); ++j) {
182 q.dnsclass = PJ_DNS_CLASS_IN;
183 q.type = PJ_DNS_TYPE_SRV;
184
185 q.name.ptr = buf;
186 pj_bzero(buf, sizeof(buf));
187 pj_strcpy2(&q.name, services[j]);
188 pj_strcat(&q.name, &ans[i].rdata.srv.target);
189
190 pj_bzero(&pkt, sizeof(pkt));
191 pkt.hdr.qdcount = 1;
192 pkt.hdr.flags = PJ_DNS_SET_QR(1) |
193 PJ_DNS_SET_RCODE(PJ_DNS_RCODE_NXDOMAIN);
194 pkt.q = &q;
195
196 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
197 }
198 }
199
200
201 /*
202 * ANOTHER DOMAIN.
203 *
204 * This time we let SRV and A get answered in different DNS
205 * query.
206 */
207
208 /* The "domain.com" DNS records (note the different the port):
209
210 _sip._tcp.domain.com 3600 IN SRV 1 0 50060 sip06.domain.com.
211 _sip._tcp.domain.com 3600 IN SRV 2 0 50060 sip07.domain.com.
212
213 sip06.domain.com. 3600 IN A 6.6.6.6
214 sip07.domain.com. 3600 IN A 7.7.7.7
215 */
216
217 pj_bzero(&pkt, sizeof(pkt));
218 pj_bzero(&ans, sizeof(ans));
219 pkt.hdr.flags = PJ_DNS_SET_QR(1);
220 pkt.hdr.anscount = 2;
221 pkt.ans = ans;
222
223 /* Add the SRV records, with reverse priority (to test that sorting
224 * works.
225 */
226 ans[0].name = pj_str("_sip._tcp.domain.com");
227 ans[0].type = PJ_DNS_TYPE_SRV;
228 ans[0].dnsclass = PJ_DNS_CLASS_IN;
229 ans[0].ttl = 3600;
230 ans[0].rdata.srv.prio = 2;
231 ans[0].rdata.srv.weight = 0;
232 ans[0].rdata.srv.port = 50060;
233 ans[0].rdata.srv.target = pj_str("SIP07.DOMAIN.COM");
234
235 ans[1].name = pj_str("_sip._tcp.domain.com");
236 ans[1].type = PJ_DNS_TYPE_SRV;
237 ans[1].dnsclass = PJ_DNS_CLASS_IN;
238 ans[1].ttl = 3600;
239 ans[1].rdata.srv.prio = 1;
240 ans[1].rdata.srv.weight = 0;
241 ans[1].rdata.srv.port = 50060;
242 ans[1].rdata.srv.target = pj_str("SIP06.DOMAIN.COM");
243
244 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
245
246 /* From herein there is only one answer */
247 pkt.hdr.anscount = 1;
248
249 /* Add a single SRV for UDP */
250 ans[0].name = pj_str("_sip._udp.domain.com");
251 ans[0].type = PJ_DNS_TYPE_SRV;
252 ans[0].dnsclass = PJ_DNS_CLASS_IN;
253 ans[0].ttl = 3600;
254 ans[0].rdata.srv.prio = 0;
255 ans[0].rdata.srv.weight = 0;
256 ans[0].rdata.srv.port = 50060;
257 ans[0].rdata.srv.target = pj_str("SIP06.DOMAIN.COM");
258
259 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
260
261
262 /* Add the A record for sip06.domain.com */
263 ans[0].name = pj_str("sip06.domain.com");
264 ans[0].type = PJ_DNS_TYPE_A;
265 ans[0].dnsclass = PJ_DNS_CLASS_IN;
266 ans[0].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000267 ans[0].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "6.6.6.6"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000268
Benny Prijonod4791af2007-06-19 08:46:02 +0000269 pkt.hdr.qdcount = 1;
270 pkt.q = &q;
271 q.name = ans[0].name;
272 q.type = ans[0].type;
273 q.dnsclass = ans[0].dnsclass;
274
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000275 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
276
277 /* Add the A record for sip07.domain.com */
278 ans[0].name = pj_str("sip07.domain.com");
279 ans[0].type = PJ_DNS_TYPE_A;
280 ans[0].dnsclass = PJ_DNS_CLASS_IN;
281 ans[0].ttl = 3600;
Benny Prijono91475442007-03-03 02:13:55 +0000282 ans[0].rdata.a.ip_addr = pj_inet_addr(pj_cstr(&tmp, "7.7.7.7"));
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000283
Benny Prijonod4791af2007-06-19 08:46:02 +0000284 pkt.hdr.qdcount = 1;
285 pkt.q = &q;
286 q.name = ans[0].name;
287 q.type = ans[0].type;
288 q.dnsclass = ans[0].dnsclass;
289
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000290 pj_dns_resolver_add_entry( resv, &pkt, PJ_FALSE);
Benny Prijonod4791af2007-06-19 08:46:02 +0000291
292 pkt.hdr.qdcount = 0;
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000293}
294
295
296/*
297 * Perform server resolution where the results are expected to
298 * come in strict order.
299 */
300static int test_resolve(const char *title,
301 pj_pool_t *pool,
302 pjsip_transport_type_e type,
303 char *name,
304 int port,
305 pjsip_server_addresses *ref)
306{
307 pjsip_host_info dest;
308 struct result result;
309
310 PJ_LOG(3,(THIS_FILE, " test_resolve(): %s", title));
311
312 dest.type = type;
313 dest.flag = pjsip_transport_get_flag_from_type(type);
314 dest.addr.host = pj_str(name);
315 dest.addr.port = port;
316
317 result.status = 0x12345678;
318
319 pjsip_endpt_resolve(endpt, pool, &dest, &result, &cb);
320
321 while (result.status == 0x12345678) {
322 int i = 0;
323 pj_time_val timeout = { 1, 0 };
324 pjsip_endpt_handle_events(endpt, &timeout);
325 if (i == 1)
326 pj_dns_resolver_dump(pjsip_endpt_get_resolver(endpt), PJ_TRUE);
327 }
328
329 if (result.status != PJ_SUCCESS) {
330 app_perror(" pjsip_endpt_resolve() error", result.status);
331 return result.status;
332 }
333
334 if (ref) {
335 unsigned i;
336
337 if (ref->count != result.servers.count) {
338 PJ_LOG(3,(THIS_FILE, " test_resolve() error 10: result count mismatch"));
339 return 10;
340 }
341
342 for (i=0; i<ref->count; ++i) {
343 pj_sockaddr_in *ra = (pj_sockaddr_in *)&ref->entry[i].addr;
344 pj_sockaddr_in *rb = (pj_sockaddr_in *)&result.servers.entry[i].addr;
345
346 if (ra->sin_addr.s_addr != rb->sin_addr.s_addr) {
347 PJ_LOG(3,(THIS_FILE, " test_resolve() error 20: IP address mismatch"));
348 return 20;
349 }
350 if (ra->sin_port != rb->sin_port) {
351 PJ_LOG(3,(THIS_FILE, " test_resolve() error 30: port mismatch"));
352 return 30;
353 }
354 if (ref->entry[i].addr_len != result.servers.entry[i].addr_len) {
355 PJ_LOG(3,(THIS_FILE, " test_resolve() error 40: addr_len mismatch"));
356 return 40;
357 }
358 if (ref->entry[i].type != result.servers.entry[i].type) {
359 PJ_LOG(3,(THIS_FILE, " test_resolve() error 50: transport type mismatch"));
360 return 50;
361 }
362 }
363 }
364
365 return PJ_SUCCESS;
366}
367
368/*
369 * Perform round-robin/load balance test.
370 */
371static int round_robin_test(pj_pool_t *pool)
372{
373 enum { COUNT = 400, PCT_ALLOWANCE = 5 };
374 unsigned i;
375 struct server_hit
376 {
377 char *ip_addr;
378 unsigned percent;
379 unsigned hits;
380 } server_hit[] =
381 {
382 { "1.1.1.1", 3, 0 },
383 { "2.2.2.2", 65, 0 },
384 { "3.3.3.3", 32, 0 },
385 { "4.4.4.4", 0, 0 }
386 };
387
388 PJ_LOG(3,(THIS_FILE, " Performing round-robin/load-balance test.."));
389
390 /* Do multiple resolve request to "example.com".
391 * The resolver should select the server based on the weight proportion
392 * the the servers in the SRV entry.
393 */
394 for (i=0; i<COUNT; ++i) {
395 pjsip_host_info dest;
396 struct result result;
397 unsigned j;
398
399 dest.type = PJSIP_TRANSPORT_UDP;
400 dest.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
401 dest.addr.host = pj_str("example.com");
402 dest.addr.port = 0;
403
404 result.status = 0x12345678;
405
406 pjsip_endpt_resolve(endpt, pool, &dest, &result, &cb);
407
408 while (result.status == 0x12345678) {
409 int i = 0;
410 pj_time_val timeout = { 1, 0 };
411 pjsip_endpt_handle_events(endpt, &timeout);
412 if (i == 1)
413 pj_dns_resolver_dump(pjsip_endpt_get_resolver(endpt), PJ_TRUE);
414 }
415
416 /* Find which server was "hit" */
417 for (j=0; j<PJ_ARRAY_SIZE(server_hit); ++j) {
418 pj_str_t tmp;
419 pj_in_addr a1;
420 pj_sockaddr_in *a2;
421
422 tmp = pj_str(server_hit[j].ip_addr);
423 a1 = pj_inet_addr(&tmp);
424 a2 = (pj_sockaddr_in*) &result.servers.entry[0].addr;
425
426 if (a1.s_addr == a2->sin_addr.s_addr) {
427 server_hit[j].hits++;
428 break;
429 }
430 }
431
432 if (j == PJ_ARRAY_SIZE(server_hit)) {
433 PJ_LOG(1,(THIS_FILE, "..round_robin_test() error 10: returned address mismatch"));
434 return 10;
435 }
436 }
437
438 /* Print the actual hit rate */
439 for (i=0; i<PJ_ARRAY_SIZE(server_hit); ++i) {
440 PJ_LOG(3,(THIS_FILE, " ..Server %s: weight=%d%%, hit %d%% times",
441 server_hit[i].ip_addr, server_hit[i].percent,
442 (server_hit[i].hits * 100) / COUNT));
443 }
444
445 /* Compare the actual hit with the weight proportion */
446 for (i=0; i<PJ_ARRAY_SIZE(server_hit); ++i) {
447 int actual_pct = (server_hit[i].hits * 100) / COUNT;
448
449 if (actual_pct + PCT_ALLOWANCE < (int)server_hit[i].percent ||
450 actual_pct - PCT_ALLOWANCE > (int)server_hit[i].percent)
451 {
452 PJ_LOG(1,(THIS_FILE,
453 "..round_robin_test() error 20: "
454 "hit rate difference for server %s (%d%%) is more than "
455 "tolerable allowance (%d%%)",
456 server_hit[i].ip_addr,
457 actual_pct - server_hit[i].percent,
458 PCT_ALLOWANCE));
459 return 20;
460 }
461 }
462
463 PJ_LOG(3,(THIS_FILE,
464 " Load balance test success, hit-rate is "
465 "within %d%% allowance", PCT_ALLOWANCE));
466 return PJ_SUCCESS;
467}
468
469
470#define C(expr) status = expr; \
471 if (status != PJ_SUCCESS) app_perror(THIS_FILE, "Error", status);
472
473static void add_ref(pjsip_server_addresses *r,
474 pjsip_transport_type_e type,
475 char *addr,
476 int port)
477{
478 pj_sockaddr_in *a;
479 pj_str_t tmp;
480
481 r->entry[r->count].type = type;
482 r->entry[r->count].priority = 0;
483 r->entry[r->count].weight = 0;
484 r->entry[r->count].addr_len = sizeof(pj_sockaddr_in);
485
486 a = (pj_sockaddr_in *)&r->entry[r->count].addr;
Benny Prijono8ab968f2007-07-20 08:08:30 +0000487 a->sin_family = pj_AF_INET();
Benny Prijonofa9e5b12006-10-08 12:39:34 +0000488 tmp = pj_str(addr);
489 a->sin_addr = pj_inet_addr(&tmp);
490 a->sin_port = pj_htons((pj_uint16_t)port);
491
492 r->count++;
493}
494
495static void create_ref(pjsip_server_addresses *r,
496 pjsip_transport_type_e type,
497 char *addr,
498 int port)
499{
500 r->count = 0;
501 add_ref(r, type, addr, port);
502}
503
504
505/*
506 * Main test entry.
507 */
508int resolve_test(void)
509{
510 pj_pool_t *pool;
511 pj_dns_resolver *resv;
512 pj_str_t nameserver;
513 pj_uint16_t port = 5353;
514 pj_status_t status;
515
516 pool = pjsip_endpt_create_pool(endpt, NULL, 4000, 4000);
517
518 status = pjsip_endpt_create_resolver(endpt, &resv);
519
520 nameserver = pj_str("192.168.0.106");
521 pj_dns_resolver_set_ns(resv, 1, &nameserver, &port);
522 pjsip_endpt_set_resolver(endpt, resv);
523
524 add_dns_entries(resv);
525
526 /* These all should be resolved as IP addresses (DNS A query) */
527 {
528 pjsip_server_addresses ref;
529 create_ref(&ref, PJSIP_TRANSPORT_UDP, "1.1.1.1", 5060);
530 status = test_resolve("IP address without transport and port", pool, PJSIP_TRANSPORT_UNSPECIFIED, "1.1.1.1", 0, &ref);
531 if (status != PJ_SUCCESS)
532 return -100;
533 }
534 {
535 pjsip_server_addresses ref;
536 create_ref(&ref, PJSIP_TRANSPORT_UDP, "1.1.1.1", 5060);
537 status = test_resolve("IP address with explicit port", pool, PJSIP_TRANSPORT_UNSPECIFIED, "1.1.1.1", 5060, &ref);
538 if (status != PJ_SUCCESS)
539 return -110;
540 }
541 {
542 pjsip_server_addresses ref;
543 create_ref(&ref, PJSIP_TRANSPORT_TCP, "1.1.1.1", 5060);
544 status = test_resolve("IP address without port (TCP)", pool, PJSIP_TRANSPORT_TCP,"1.1.1.1", 0, &ref);
545 if (status != PJ_SUCCESS)
546 return -120;
547 }
548 {
549 pjsip_server_addresses ref;
550 create_ref(&ref, PJSIP_TRANSPORT_TLS, "1.1.1.1", 5061);
551 status = test_resolve("IP address without port (TLS)", pool, PJSIP_TRANSPORT_TLS, "1.1.1.1", 0, &ref);
552 if (status != PJ_SUCCESS)
553 return -130;
554 }
555
556 /* This should be resolved as DNS A record (because port is present) */
557 {
558 pjsip_server_addresses ref;
559 create_ref(&ref, PJSIP_TRANSPORT_UDP, "5.5.5.5", 5060);
560 status = test_resolve("domain name with port should resolve to A record", pool, PJSIP_TRANSPORT_UNSPECIFIED, "example.com", 5060, &ref);
561 if (status != PJ_SUCCESS)
562 return -140;
563 }
564
565 /* This will fail to be resolved as SRV, resolver should fallback to
566 * resolving to A record.
567 */
568 {
569 pjsip_server_addresses ref;
570 create_ref(&ref, PJSIP_TRANSPORT_UDP, "2.2.2.2", 5060);
571 status = test_resolve("failure with SRV fallback to A record", pool, PJSIP_TRANSPORT_UNSPECIFIED, "sip02.example.com", 0, &ref);
572 if (status != PJ_SUCCESS)
573 return -150;
574 }
575
576 /* Same as above, but explicitly for TLS. */
577 {
578 pjsip_server_addresses ref;
579 create_ref(&ref, PJSIP_TRANSPORT_TLS, "2.2.2.2", 5061);
580 status = test_resolve("failure with SRV fallback to A record (for TLS)", pool, PJSIP_TRANSPORT_TLS, "sip02.example.com", 0, &ref);
581 if (status != PJ_SUCCESS)
582 return -150;
583 }
584
585 /* Standard DNS SRV followed by A recolution */
586 {
587 pjsip_server_addresses ref;
588 create_ref(&ref, PJSIP_TRANSPORT_UDP, "6.6.6.6", 50060);
589 status = test_resolve("standard SRV resolution", pool, PJSIP_TRANSPORT_UNSPECIFIED, "domain.com", 0, &ref);
590 if (status != PJ_SUCCESS)
591 return -155;
592 }
593
594 /* Standard DNS SRV followed by A recolution (explicit transport) */
595 {
596 pjsip_server_addresses ref;
597 create_ref(&ref, PJSIP_TRANSPORT_TCP, "6.6.6.6", 50060);
598 add_ref(&ref, PJSIP_TRANSPORT_TCP, "7.7.7.7", 50060);
599 status = test_resolve("standard SRV resolution with explicit transport (TCP)", pool, PJSIP_TRANSPORT_TCP, "domain.com", 0, &ref);
600 if (status != PJ_SUCCESS)
601 return -160;
602 }
603
604
605 /* Round robin/load balance test */
606 if (round_robin_test(pool) != 0)
607 return -170;
608
609 /* Timeout test */
610 {
611 status = test_resolve("timeout test", pool, PJSIP_TRANSPORT_UNSPECIFIED, "an.invalid.address", 0, NULL);
612 if (status == PJ_SUCCESS)
613 return -150;
614 }
615
616 return 0;
617}
618