d800c55822511bcfa6a3ca2e9e1e23c5d3cae309
[asterisk/asterisk.git] / channels / sip / config_parser.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*!
18  * \file
19  * \brief sip config parsing functions and unit tests
20  */
21
22 #include "asterisk.h"
23
24 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
25
26 #include "include/sip.h"
27 #include "include/config_parser.h"
28 #include "include/sip_utils.h"
29
30 /*! \brief Parse register=> line in sip.conf
31  *
32  * \retval 0 on success
33  * \retval -1 on failure
34  */
35 int sip_parse_register_line(struct sip_registry *reg, int default_expiry, const char *value, int lineno)
36 {
37         int portnum = 0;
38         enum sip_transport transport = SIP_TRANSPORT_UDP;
39         char buf[256] = "";
40         char *userpart = NULL, *hostpart = NULL;
41         /* register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] */
42         AST_DECLARE_APP_ARGS(pre1,
43                 AST_APP_ARG(peer);
44                 AST_APP_ARG(userpart);
45         );
46         AST_DECLARE_APP_ARGS(pre2,
47                 AST_APP_ARG(transport);
48                 AST_APP_ARG(blank);
49                 AST_APP_ARG(userpart);
50         );
51         AST_DECLARE_APP_ARGS(user1,
52                 AST_APP_ARG(userpart);
53                 AST_APP_ARG(secret);
54                 AST_APP_ARG(authuser);
55         );
56         AST_DECLARE_APP_ARGS(host1,
57                 AST_APP_ARG(hostpart);
58                 AST_APP_ARG(expiry);
59         );
60         AST_DECLARE_APP_ARGS(host2,
61                 AST_APP_ARG(hostpart);
62                 AST_APP_ARG(extension);
63         );
64         AST_DECLARE_APP_ARGS(host3,
65                 AST_APP_ARG(host);
66                 AST_APP_ARG(port);
67         );
68
69         if (!value) {
70                 return -1;
71         }
72
73         if (!reg) {
74                 return -1;
75         }
76         ast_copy_string(buf, value, sizeof(buf));
77
78         /*! register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
79          * becomes
80          *   userpart => [peer?][transport://]user[@domain][:secret[:authuser]]
81          *   hostpart => host[:port][/extension][~expiry]
82          */
83         if ((hostpart = strrchr(buf, '@'))) {
84                 *hostpart++ = '\0';
85                 userpart = buf;
86         }
87
88         if (ast_strlen_zero(userpart) || ast_strlen_zero(hostpart)) {
89                 ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
90                 return -1;
91         }
92
93         /*!
94          * pre1.peer => peer
95          * pre1.userpart => [transport://]user[@domain][:secret[:authuser]]
96          * hostpart => host[:port][/extension][~expiry]
97          */
98         AST_NONSTANDARD_RAW_ARGS(pre1, userpart, '?');
99         if (ast_strlen_zero(pre1.userpart)) {
100                 pre1.userpart = pre1.peer;
101                 pre1.peer = NULL;
102         }
103
104         /*!
105          * pre1.peer => peer
106          * pre2.transport = transport
107          * pre2.userpart => user[@domain][:secret[:authuser]]
108          * hostpart => host[:port][/extension][~expiry]
109          */
110         AST_NONSTANDARD_RAW_ARGS(pre2, pre1.userpart, '/');
111         if (ast_strlen_zero(pre2.userpart)) {
112                 pre2.userpart = pre2.transport;
113                 pre2.transport = NULL;
114         } else {
115                 pre2.transport[strlen(pre2.transport) - 1] = '\0'; /* Remove trailing : */
116         }
117
118         if (!ast_strlen_zero(pre2.blank)) {
119                 ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
120                 return -1;
121         }
122
123         /*!
124          * pre1.peer => peer
125          * pre2.transport = transport
126          * user1.userpart => user[@domain]
127          * user1.secret => secret
128          * user1.authuser => authuser
129          * hostpart => host[:port][/extension][~expiry]
130          */
131         AST_NONSTANDARD_RAW_ARGS(user1, pre2.userpart, ':');
132
133         /*!
134          * pre1.peer => peer
135          * pre2.transport = transport
136          * user1.userpart => user[@domain]
137          * user1.secret => secret
138          * user1.authuser => authuser
139          * host1.hostpart => host[:port][/extension]
140          * host1.expiry => [expiry]
141          */
142         AST_NONSTANDARD_RAW_ARGS(host1, hostpart, '~');
143
144         /*!
145          * pre1.peer => peer
146          * pre2.transport = transport
147          * user1.userpart => user[@domain]
148          * user1.secret => secret
149          * user1.authuser => authuser
150          * host2.hostpart => host[:port]
151          * host2.extension => [extension]
152          * host1.expiry => [expiry]
153          */
154         AST_NONSTANDARD_RAW_ARGS(host2, host1.hostpart, '/');
155
156         /*!
157          * pre1.peer => peer
158          * pre2.transport = transport
159          * user1.userpart => user[@domain]
160          * user1.secret => secret
161          * user1.authuser => authuser
162          * host3.host => host
163          * host3.port => port
164          * host2.extension => extension
165          * host1.expiry => expiry
166          */
167         AST_NONSTANDARD_RAW_ARGS(host3, host2.hostpart, ':');
168
169         if (host3.port) {
170                 if (!(portnum = port_str2int(host3.port, 0))) {
171                         ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", host3.port, lineno);
172                 }
173         }
174
175         /* set transport type */
176         if (!pre2.transport) {
177                 transport = SIP_TRANSPORT_UDP;
178         } else if (!strncasecmp(pre2.transport, "tcp", 3)) {
179                 transport = SIP_TRANSPORT_TCP;
180         } else if (!strncasecmp(pre2.transport, "tls", 3)) {
181                 transport = SIP_TRANSPORT_TLS;
182         } else if (!strncasecmp(pre2.transport, "udp", 3)) {
183                 transport = SIP_TRANSPORT_UDP;
184         } else {
185                 transport = SIP_TRANSPORT_UDP;
186                 ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", pre2.transport, lineno);
187         }
188
189         /* if no portnum specified, set default for transport */
190         if (!portnum) {
191                 if (transport == SIP_TRANSPORT_TLS) {
192                         portnum = STANDARD_TLS_PORT;
193                 } else {
194                         portnum = STANDARD_SIP_PORT;
195                 }
196         }
197
198         /* copy into sip_registry object */
199         ast_string_field_set(reg, callback, ast_strip_quoted(S_OR(host2.extension, "s"), "\"", "\""));
200         ast_string_field_set(reg, username, ast_strip_quoted(S_OR(user1.userpart, ""), "\"", "\""));
201         ast_string_field_set(reg, hostname, ast_strip_quoted(S_OR(host3.host, ""), "\"", "\""));
202         ast_string_field_set(reg, authuser, ast_strip_quoted(S_OR(user1.authuser, ""), "\"", "\""));
203         ast_string_field_set(reg, secret, ast_strip_quoted(S_OR(user1.secret, ""), "\"", "\""));
204         ast_string_field_set(reg, peername, ast_strip_quoted(S_OR(pre1.peer, ""), "\"", "\""));
205
206         reg->transport = transport;
207         reg->timeout = reg->expire = -1;
208         reg->portno = portnum;
209         reg->callid_valid = FALSE;
210         reg->ocseq = INITIAL_CSEQ;
211         reg->refresh = reg->expiry = reg->configured_expiry = (host1.expiry ? atoi(ast_strip_quoted(host1.expiry, "\"", "\"")) : default_expiry);
212
213         return 0;
214 }
215
216 AST_TEST_DEFINE(sip_parse_register_line_test)
217 {
218         int res = AST_TEST_PASS;
219         struct sip_registry *reg;
220         int default_expiry = 120;
221         const char *reg1 = "name@domain";
222         const char *reg2 = "name:pass@domain";
223         const char *reg3 = "name@namedomain:pass:authuser@domain";
224         const char *reg4 = "name@namedomain:pass:authuser@domain/extension";
225         const char *reg5 = "tcp://name@namedomain:pass:authuser@domain/extension";
226         const char *reg6 = "tls://name@namedomain:pass:authuser@domain/extension~111";
227         const char *reg7 = "peer?tcp://name@namedomain:pass:authuser@domain:1234/extension~111";
228         const char *reg8 = "peer?name@namedomain:pass:authuser@domain:1234/extension~111";
229         const char *reg9 = "peer?name:pass:authuser:1234/extension~111";
230         const char *reg10 = "@domin:1234";
231
232         switch (cmd) {
233         case TEST_INIT:
234                 info->name = "sip_parse_register_line_test";
235                 info->category = "channels/chan_sip/";
236                 info->summary = "tests sip register line parsing";
237                 info->description =
238                                                         "Tests parsing of various register line configurations. "
239                                                         "Verifies output matches expected behavior.";
240                 return AST_TEST_NOT_RUN;
241         case TEST_EXECUTE:
242                 break;
243         }
244
245         /* ---Test reg 1, simple config --- */
246         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
247                 goto alloc_fail;
248         } else if (
249             sip_parse_register_line(reg, default_expiry, reg1, 1) ||
250                 strcmp(reg->callback, "s")           ||
251                 strcmp(reg->username, "name")       ||
252                 strcmp(reg->hostname, "domain")     ||
253                 strcmp(reg->authuser, "")           ||
254                 strcmp(reg->secret, "")             ||
255                 strcmp(reg->peername, "")           ||
256                 reg->transport != SIP_TRANSPORT_UDP ||
257                 reg->timeout != -1                  ||
258                 reg->expire != -1                   ||
259                 reg->refresh != default_expiry ||
260                 reg->expiry != default_expiry ||
261                 reg->configured_expiry != default_expiry ||
262                 reg->portno != STANDARD_SIP_PORT    ||
263                 reg->callid_valid != FALSE          ||
264                 reg->ocseq != INITIAL_CSEQ) {
265
266                 ast_test_status_update(test, "Test 1: simple config failed\n");
267                 res = AST_TEST_FAIL;
268         }
269         ast_string_field_free_memory(reg);
270         ast_free(reg);
271
272         /* ---Test reg 2, add secret --- */
273         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
274                 goto alloc_fail;
275         } else if (
276             sip_parse_register_line(reg, default_expiry, reg2, 1) ||
277                 strcmp(reg->callback, "s")           ||
278                 strcmp(reg->username, "name")       ||
279                 strcmp(reg->hostname, "domain")     ||
280                 strcmp(reg->authuser, "")           ||
281                 strcmp(reg->secret, "pass")         ||
282                 strcmp(reg->peername, "")           ||
283                 reg->transport != SIP_TRANSPORT_UDP ||
284                 reg->timeout != -1                  ||
285                 reg->expire != -1                   ||
286                 reg->refresh != default_expiry ||
287                 reg->expiry != default_expiry ||
288                 reg->configured_expiry != default_expiry ||
289                 reg->portno != STANDARD_SIP_PORT    ||
290                 reg->callid_valid != FALSE          ||
291                 reg->ocseq != INITIAL_CSEQ) {
292
293                 ast_test_status_update(test,  "Test 2: add secret failed\n");
294                 res = AST_TEST_FAIL;
295         }
296         ast_string_field_free_memory(reg);
297         ast_free(reg);
298
299         /* ---Test reg 3, add userdomain and authuser --- */
300         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
301                 goto alloc_fail;
302         } else if (
303             sip_parse_register_line(reg, default_expiry, reg3, 1) ||
304                 strcmp(reg->callback, "s")           ||
305                 strcmp(reg->username, "name@namedomain") ||
306                 strcmp(reg->hostname, "domain")     ||
307                 strcmp(reg->authuser, "authuser")           ||
308                 strcmp(reg->secret, "pass")         ||
309                 strcmp(reg->peername, "")           ||
310                 reg->transport != SIP_TRANSPORT_UDP ||
311                 reg->timeout != -1                  ||
312                 reg->expire != -1                   ||
313                 reg->refresh != default_expiry ||
314                 reg->expiry != default_expiry ||
315                 reg->configured_expiry != default_expiry ||
316                 reg->portno != STANDARD_SIP_PORT    ||
317                 reg->callid_valid != FALSE          ||
318                 reg->ocseq != INITIAL_CSEQ) {
319
320                 ast_test_status_update(test, "Test 3: add userdomain and authuser failed\n");
321                 res = AST_TEST_FAIL;
322         }
323         ast_string_field_free_memory(reg);
324         ast_free(reg);
325
326         /* ---Test reg 4, add callback extension --- */
327         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
328                 goto alloc_fail;
329         } else if (
330             sip_parse_register_line(reg, default_expiry, reg4, 1) ||
331                 strcmp(reg->callback, "extension")           ||
332                 strcmp(reg->username, "name@namedomain") ||
333                 strcmp(reg->hostname, "domain")     ||
334                 strcmp(reg->authuser, "authuser")           ||
335                 strcmp(reg->secret, "pass")         ||
336                 strcmp(reg->peername, "")           ||
337                 reg->transport != SIP_TRANSPORT_UDP ||
338                 reg->timeout != -1                  ||
339                 reg->expire != -1                   ||
340                 reg->refresh != default_expiry ||
341                 reg->expiry != default_expiry ||
342                 reg->configured_expiry != default_expiry ||
343                 reg->portno != STANDARD_SIP_PORT    ||
344                 reg->callid_valid != FALSE          ||
345                 reg->ocseq != INITIAL_CSEQ) {
346
347                 ast_test_status_update(test, "Test 4: add callback extension failed\n");
348                 res = AST_TEST_FAIL;
349         }
350         ast_string_field_free_memory(reg);
351         ast_free(reg);
352
353         /* ---Test reg 5, add transport --- */
354         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
355                 goto alloc_fail;
356         } else if (
357             sip_parse_register_line(reg, default_expiry, reg5, 1) ||
358                 strcmp(reg->callback, "extension")           ||
359                 strcmp(reg->username, "name@namedomain") ||
360                 strcmp(reg->hostname, "domain")     ||
361                 strcmp(reg->authuser, "authuser")           ||
362                 strcmp(reg->secret, "pass")         ||
363                 strcmp(reg->peername, "")           ||
364                 reg->transport != SIP_TRANSPORT_TCP ||
365                 reg->timeout != -1                  ||
366                 reg->expire != -1                   ||
367                 reg->refresh != default_expiry ||
368                 reg->expiry != default_expiry ||
369                 reg->configured_expiry != default_expiry ||
370                 reg->portno != STANDARD_SIP_PORT    ||
371                 reg->callid_valid != FALSE          ||
372                 reg->ocseq != INITIAL_CSEQ) {
373
374                 ast_test_status_update(test, "Test 5: add transport failed\n");
375                 res = AST_TEST_FAIL;
376         }
377         ast_string_field_free_memory(reg);
378         ast_free(reg);
379
380         /* ---Test reg 6, change to tls transport, add expiry  --- */
381         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
382                 goto alloc_fail;
383         } else if (
384             sip_parse_register_line(reg, default_expiry, reg6, 1) ||
385                 strcmp(reg->callback, "extension")           ||
386                 strcmp(reg->username, "name@namedomain") ||
387                 strcmp(reg->hostname, "domain")     ||
388                 strcmp(reg->authuser, "authuser")           ||
389                 strcmp(reg->secret, "pass")         ||
390                 strcmp(reg->peername, "")           ||
391                 reg->transport != SIP_TRANSPORT_TLS ||
392                 reg->timeout != -1                  ||
393                 reg->expire != -1                   ||
394                 reg->refresh != 111 ||
395                 reg->expiry != 111 ||
396                 reg->configured_expiry != 111 ||
397                 reg->portno != STANDARD_TLS_PORT    ||
398                 reg->callid_valid != FALSE          ||
399                 reg->ocseq != INITIAL_CSEQ) {
400
401                 ast_test_status_update(test, "Test 6: change to tls transport and add expiry failed\n");
402                 res = AST_TEST_FAIL;
403         }
404         ast_string_field_free_memory(reg);
405         ast_free(reg);
406
407         /* ---Test reg 7, change transport to tcp, add custom port, and add peer --- */
408         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
409                 goto alloc_fail;
410         } else if (
411             sip_parse_register_line(reg, default_expiry, reg7, 1) ||
412                 strcmp(reg->callback, "extension")           ||
413                 strcmp(reg->username, "name@namedomain") ||
414                 strcmp(reg->hostname, "domain")     ||
415                 strcmp(reg->authuser, "authuser")           ||
416                 strcmp(reg->secret, "pass")         ||
417                 strcmp(reg->peername, "peer")           ||
418                 reg->transport != SIP_TRANSPORT_TCP ||
419                 reg->timeout != -1                  ||
420                 reg->expire != -1                   ||
421                 reg->refresh != 111 ||
422                 reg->expiry != 111 ||
423                 reg->configured_expiry != 111 ||
424                 reg->portno != 1234    ||
425                 reg->callid_valid != FALSE          ||
426                 reg->ocseq != INITIAL_CSEQ) {
427
428                 ast_test_status_update(test, "Test 7, change transport to tcp, add custom port, and add peer failed.\n");
429                 res = AST_TEST_FAIL;
430         }
431         ast_string_field_free_memory(reg);
432         ast_free(reg);
433
434         /* ---Test reg 8, remove transport --- */
435         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
436                 goto alloc_fail;
437         } else if (
438             sip_parse_register_line(reg, default_expiry, reg8, 1) ||
439                 strcmp(reg->callback, "extension")           ||
440                 strcmp(reg->username, "name@namedomain") ||
441                 strcmp(reg->hostname, "domain")     ||
442                 strcmp(reg->authuser, "authuser")           ||
443                 strcmp(reg->secret, "pass")         ||
444                 strcmp(reg->peername, "peer")           ||
445                 reg->transport != SIP_TRANSPORT_UDP ||
446                 reg->timeout != -1                  ||
447                 reg->expire != -1                   ||
448                 reg->refresh != 111 ||
449                 reg->expiry != 111 ||
450                 reg->configured_expiry != 111 ||
451                 reg->portno != 1234    ||
452                 reg->callid_valid != FALSE          ||
453                 reg->ocseq != INITIAL_CSEQ) {
454
455                 ast_test_status_update(test, "Test 8, remove transport failed.\n");
456                 res = AST_TEST_FAIL;
457         }
458         ast_string_field_free_memory(reg);
459         ast_free(reg);
460
461         /* ---Test reg 9, missing domain, expected to fail --- */
462         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
463                 goto alloc_fail;
464         } else if (!sip_parse_register_line(reg, default_expiry, reg9, 1)) {
465                 ast_test_status_update(test,
466                                 "Test 9, missing domain, expected to fail but did not.\n");
467                 res = AST_TEST_FAIL;
468         }
469         ast_string_field_free_memory(reg);
470         ast_free(reg);
471
472         /* ---Test reg 10,  missing user, expected to fail --- */
473         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
474                 goto alloc_fail;
475         } else if (!sip_parse_register_line(reg, default_expiry, reg10, 1)) {
476                 ast_test_status_update(test,
477                                 "Test 10, missing user expected to fail but did not\n");
478                 res = AST_TEST_FAIL;
479         }
480         ast_string_field_free_memory(reg);
481         ast_free(reg);
482
483         /* ---Test reg 11, no registry object, expected to fail--- */
484         if (!sip_parse_register_line(NULL, default_expiry, reg1, 1)) {
485                 ast_test_status_update(test,
486                                 "Test 11, no registery object, expected to fail but did not.\n");
487                 res = AST_TEST_FAIL;
488         }
489
490         /* ---Test reg 11,  no registry line, expected to fail --- */
491         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
492                 goto alloc_fail;
493         } else if (!sip_parse_register_line(reg, default_expiry, NULL, 1)) {
494
495                 ast_test_status_update(test,
496                                 "Test 11, NULL register line expected to fail but did not.\n");
497                 res = AST_TEST_FAIL;
498         }
499         ast_string_field_free_memory(reg);
500         ast_free(reg);
501
502
503         return res;
504
505 alloc_fail:
506         ast_test_status_update(test, "Out of memory. \n");
507         return res;
508 }
509
510 int sip_parse_host(char *line, int lineno, char **hostname, int *portnum, enum sip_transport *transport)
511 {
512         char *port;
513
514         if (ast_strlen_zero(line)) {
515                 return -1;
516         }
517         if ((*hostname = strstr(line, "://"))) {
518                 *hostname += 3;
519
520                 if (!strncasecmp(line, "tcp", 3))
521                         *transport = SIP_TRANSPORT_TCP;
522                 else if (!strncasecmp(line, "tls", 3))
523                         *transport = SIP_TRANSPORT_TLS;
524                 else if (!strncasecmp(line, "udp", 3))
525                         *transport = SIP_TRANSPORT_UDP;
526                 else
527                         ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno);
528         } else {
529                 *hostname = line;
530                 *transport = SIP_TRANSPORT_UDP;
531         }
532
533         if ((line = strrchr(*hostname, '@')))
534                 line++;
535         else
536                 line = *hostname;
537
538         if ((port = strrchr(line, ':'))) {
539                 *port++ = '\0';
540
541                 if (!sscanf(port, "%5u", portnum)) {
542                         ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno);
543                         port = NULL;
544                 }
545         }
546
547         if (!port) {
548                 if (*transport & SIP_TRANSPORT_TLS) {
549                         *portnum = STANDARD_TLS_PORT;
550                 } else {
551                         *portnum = STANDARD_SIP_PORT;
552                 }
553         }
554
555         return 0;
556 }
557
558 AST_TEST_DEFINE(sip_parse_host_line_test)
559 {
560         int res = AST_TEST_PASS;
561         char *host;
562         int port;
563         enum sip_transport transport;
564         char host1[] = "www.blah.com";
565         char host2[] = "tcp://www.blah.com";
566         char host3[] = "tls://10.10.10.10";
567         char host4[] = "tls://10.10.10.10:1234";
568         char host5[] = "10.10.10.10:1234";
569
570         switch (cmd) {
571         case TEST_INIT:
572                 info->name = "sip_parse_host_line_test";
573                 info->category = "channels/chan_sip/";
574                 info->summary = "tests sip.conf host line parsing";
575                 info->description =
576                                                         "Tests parsing of various host line configurations. "
577                                                         "Verifies output matches expected behavior.";
578                 return AST_TEST_NOT_RUN;
579         case TEST_EXECUTE:
580                 break;
581         }
582
583         /* test 1, simple host */
584         sip_parse_host(host1, 1, &host, &port, &transport);
585         if (port != STANDARD_SIP_PORT ||
586                         ast_strlen_zero(host) || strcmp(host, "www.blah.com") ||
587                         transport != SIP_TRANSPORT_UDP) {
588                 ast_test_status_update(test, "Test 1: simple host failed.\n");
589                 res = AST_TEST_FAIL;
590         }
591
592         /* test 2, add tcp transport */
593         sip_parse_host(host2, 1, &host, &port, &transport);
594         if (port != STANDARD_SIP_PORT ||
595                         ast_strlen_zero(host) || strcmp(host, "www.blah.com") ||
596                         transport != SIP_TRANSPORT_TCP) {
597                 ast_test_status_update(test, "Test 2: tcp host failed.\n");
598                 res = AST_TEST_FAIL;
599         }
600
601         /* test 3, add tls transport */
602         sip_parse_host(host3, 1, &host, &port, &transport);
603         if (port != STANDARD_TLS_PORT ||
604                         ast_strlen_zero(host) || strcmp(host, "10.10.10.10") ||
605                         transport != SIP_TRANSPORT_TLS) {
606                 ast_test_status_update(test, "Test 3: tls host failed. \n");
607                 res = AST_TEST_FAIL;
608         }
609
610         /* test 4, add custom port with tls */
611         sip_parse_host(host4, 1, &host, &port, &transport);
612         if (port != 1234 || ast_strlen_zero(host) ||
613                         strcmp(host, "10.10.10.10") ||
614                         transport != SIP_TRANSPORT_TLS) {
615                 ast_test_status_update(test, "Test 4: tls host with custom port failed.\n");
616                 res = AST_TEST_FAIL;
617         }
618
619         /* test 5, simple host with custom port */
620         sip_parse_host(host5, 1, &host, &port, &transport);
621         if (port != 1234 || ast_strlen_zero(host) ||
622                         strcmp(host, "10.10.10.10") ||
623                         transport != SIP_TRANSPORT_UDP) {
624                 ast_test_status_update(test, "Test 5: simple host with custom port failed.\n");
625                 res = AST_TEST_FAIL;
626         }
627
628         /* test 6, expected failure with NULL input */
629         if (!sip_parse_host(NULL, 1, &host, &port, &transport)) {
630                 ast_test_status_update(test, "Test 6: expected error on NULL input did not occur.\n");
631                 res = AST_TEST_FAIL;
632         }
633
634         return res;
635
636 }
637
638 /*! \brief SIP test registration */
639 void sip_config_parser_register_tests(void)
640 {
641         AST_TEST_REGISTER(sip_parse_register_line_test);
642         AST_TEST_REGISTER(sip_parse_host_line_test);
643 }
644
645 /*! \brief SIP test registration */
646 void sip_config_parser_unregister_tests(void)
647 {
648         AST_TEST_UNREGISTER(sip_parse_register_line_test);
649         AST_TEST_UNREGISTER(sip_parse_host_line_test);
650 }
651