-----Changes -----
[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, 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         if (!ast_strlen_zero(host1.expiry)) {
212                 reg->refresh = reg->expiry = reg->configured_expiry = atoi(ast_strip_quoted(host1.expiry, "\"", "\""));
213         }
214
215         return 0;
216 }
217
218 AST_TEST_DEFINE(sip_parse_register_line_test)
219 {
220         int res = AST_TEST_PASS;
221         struct sip_registry *reg;
222         const char *reg1 = "name@domain";
223         const char *reg2 = "name:pass@domain";
224         const char *reg3 = "name@namedomain:pass:authuser@domain";
225         const char *reg4 = "name@namedomain:pass:authuser@domain/extension";
226         const char *reg5 = "tcp://name@namedomain:pass:authuser@domain/extension";
227         const char *reg6 = "tls://name@namedomain:pass:authuser@domain/extension~111";
228         const char *reg7 = "peer?tcp://name@namedomain:pass:authuser@domain:1234/extension~111";
229         const char *reg8 = "peer?name@namedomain:pass:authuser@domain:1234/extension~111";
230         const char *reg9 = "peer?name:pass:authuser:1234/extension~111";
231         const char *reg10 = "@domin:1234";
232
233         switch (cmd) {
234         case TEST_INIT:
235                 info->name = "sip_parse_register_line_test";
236                 info->category = "channels/chan_sip/";
237                 info->summary = "tests sip register line parsing";
238                 info->description =
239                                                         " Tests parsing of various register line configurations."
240                                                         " Verifies output matches expected behavior.";
241                 return AST_TEST_NOT_RUN;
242         case TEST_EXECUTE:
243                 break;
244         }
245
246         /* ---Test reg 1, simple config --- */
247         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
248                 goto alloc_fail;
249         } else if (
250             sip_parse_register_line(reg, reg1, 1) ||
251                 strcmp(reg->callback, "s")           ||
252                 strcmp(reg->username, "name")       ||
253                 strcmp(reg->hostname, "domain")     ||
254                 strcmp(reg->authuser, "")           ||
255                 strcmp(reg->secret, "")             ||
256                 strcmp(reg->peername, "")           ||
257                 reg->transport != SIP_TRANSPORT_UDP ||
258                 reg->timeout != -1                  ||
259                 reg->expire != -1                   ||
260                 reg->refresh ||
261                 reg->expiry ||
262                 reg->configured_expiry ||
263                 reg->portno != STANDARD_SIP_PORT    ||
264                 reg->callid_valid != FALSE          ||
265                 reg->ocseq != INITIAL_CSEQ) {
266
267                 ast_str_append(&args->ast_test_error_str, 0, "Test 1: simple config failed\n");
268                 res = AST_TEST_FAIL;
269         }
270         ast_string_field_free_memory(reg);
271         ast_free(reg);
272
273         /* ---Test reg 2, add secret --- */
274         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
275                 goto alloc_fail;
276         } else if (
277             sip_parse_register_line(reg, reg2, 1) ||
278                 strcmp(reg->callback, "s")           ||
279                 strcmp(reg->username, "name")       ||
280                 strcmp(reg->hostname, "domain")     ||
281                 strcmp(reg->authuser, "")           ||
282                 strcmp(reg->secret, "pass")         ||
283                 strcmp(reg->peername, "")           ||
284                 reg->transport != SIP_TRANSPORT_UDP ||
285                 reg->timeout != -1                  ||
286                 reg->expire != -1                   ||
287                 reg->refresh ||
288                 reg->expiry ||
289                 reg->configured_expiry ||
290                 reg->portno != STANDARD_SIP_PORT    ||
291                 reg->callid_valid != FALSE          ||
292                 reg->ocseq != INITIAL_CSEQ) {
293
294                 ast_str_append(&args->ast_test_error_str, 0, "Test 2: add secret failed\n");
295                 res = AST_TEST_FAIL;
296         }
297         ast_string_field_free_memory(reg);
298         ast_free(reg);
299
300         /* ---Test reg 3, add userdomain and authuser --- */
301         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
302                 goto alloc_fail;
303         } else if (
304             sip_parse_register_line(reg, reg3, 1) ||
305                 strcmp(reg->callback, "s")           ||
306                 strcmp(reg->username, "name@namedomain") ||
307                 strcmp(reg->hostname, "domain")     ||
308                 strcmp(reg->authuser, "authuser")           ||
309                 strcmp(reg->secret, "pass")         ||
310                 strcmp(reg->peername, "")           ||
311                 reg->transport != SIP_TRANSPORT_UDP ||
312                 reg->timeout != -1                  ||
313                 reg->expire != -1                   ||
314                 reg->refresh ||
315                 reg->expiry ||
316                 reg->configured_expiry ||
317                 reg->portno != STANDARD_SIP_PORT    ||
318                 reg->callid_valid != FALSE          ||
319                 reg->ocseq != INITIAL_CSEQ) {
320
321                 ast_str_append(&args->ast_test_error_str, 0, "Test 3: add userdomain and authuser failed\n");
322                 res = AST_TEST_FAIL;
323         }
324         ast_string_field_free_memory(reg);
325         ast_free(reg);
326
327         /* ---Test reg 4, add callback extension --- */
328         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
329                 goto alloc_fail;
330         } else if (
331             sip_parse_register_line(reg, reg4, 1) ||
332                 strcmp(reg->callback, "extension")           ||
333                 strcmp(reg->username, "name@namedomain") ||
334                 strcmp(reg->hostname, "domain")     ||
335                 strcmp(reg->authuser, "authuser")           ||
336                 strcmp(reg->secret, "pass")         ||
337                 strcmp(reg->peername, "")           ||
338                 reg->transport != SIP_TRANSPORT_UDP ||
339                 reg->timeout != -1                  ||
340                 reg->expire != -1                   ||
341                 reg->refresh ||
342                 reg->expiry ||
343                 reg->configured_expiry ||
344                 reg->portno != STANDARD_SIP_PORT    ||
345                 reg->callid_valid != FALSE          ||
346                 reg->ocseq != INITIAL_CSEQ) {
347
348                 ast_str_append(&args->ast_test_error_str, 0, "Test 4: add callback extension failed\n");
349                 res = AST_TEST_FAIL;
350         }
351         ast_string_field_free_memory(reg);
352         ast_free(reg);
353
354         /* ---Test reg 5, add transport --- */
355         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
356                 goto alloc_fail;
357         } else if (
358             sip_parse_register_line(reg, reg5, 1) ||
359                 strcmp(reg->callback, "extension")           ||
360                 strcmp(reg->username, "name@namedomain") ||
361                 strcmp(reg->hostname, "domain")     ||
362                 strcmp(reg->authuser, "authuser")           ||
363                 strcmp(reg->secret, "pass")         ||
364                 strcmp(reg->peername, "")           ||
365                 reg->transport != SIP_TRANSPORT_TCP ||
366                 reg->timeout != -1                  ||
367                 reg->expire != -1                   ||
368                 reg->refresh ||
369                 reg->expiry ||
370                 reg->configured_expiry ||
371                 reg->portno != STANDARD_SIP_PORT    ||
372                 reg->callid_valid != FALSE          ||
373                 reg->ocseq != INITIAL_CSEQ) {
374
375                 ast_str_append(&args->ast_test_error_str, 0, "Test 5: add transport failed\n");
376                 res = AST_TEST_FAIL;
377         }
378         ast_string_field_free_memory(reg);
379         ast_free(reg);
380
381         /* ---Test reg 6, change to tls transport, add expiry  --- */
382         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
383                 goto alloc_fail;
384         } else if (
385             sip_parse_register_line(reg, reg6, 1) ||
386                 strcmp(reg->callback, "extension")           ||
387                 strcmp(reg->username, "name@namedomain") ||
388                 strcmp(reg->hostname, "domain")     ||
389                 strcmp(reg->authuser, "authuser")           ||
390                 strcmp(reg->secret, "pass")         ||
391                 strcmp(reg->peername, "")           ||
392                 reg->transport != SIP_TRANSPORT_TLS ||
393                 reg->timeout != -1                  ||
394                 reg->expire != -1                   ||
395                 reg->refresh != 111 ||
396                 reg->expiry != 111 ||
397                 reg->configured_expiry != 111 ||
398                 reg->portno != STANDARD_TLS_PORT    ||
399                 reg->callid_valid != FALSE          ||
400                 reg->ocseq != INITIAL_CSEQ) {
401
402                 ast_str_append(&args->ast_test_error_str, 0, "Test 6: change to tls transport and add expiry failed\n");
403                 res = AST_TEST_FAIL;
404         }
405         ast_string_field_free_memory(reg);
406         ast_free(reg);
407
408         /* ---Test reg 7, change transport to tcp, add custom port, and add peer --- */
409         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
410                 goto alloc_fail;
411         } else if (
412             sip_parse_register_line(reg, reg7, 1) ||
413                 strcmp(reg->callback, "extension")           ||
414                 strcmp(reg->username, "name@namedomain") ||
415                 strcmp(reg->hostname, "domain")     ||
416                 strcmp(reg->authuser, "authuser")           ||
417                 strcmp(reg->secret, "pass")         ||
418                 strcmp(reg->peername, "peer")           ||
419                 reg->transport != SIP_TRANSPORT_TCP ||
420                 reg->timeout != -1                  ||
421                 reg->expire != -1                   ||
422                 reg->refresh != 111 ||
423                 reg->expiry != 111 ||
424                 reg->configured_expiry != 111 ||
425                 reg->portno != 1234    ||
426                 reg->callid_valid != FALSE          ||
427                 reg->ocseq != INITIAL_CSEQ) {
428
429                 ast_str_append(&args->ast_test_error_str, 0, "Test 7, change transport to tcp, add custom port, and add peer failed.\n");
430                 res = AST_TEST_FAIL;
431         }
432         ast_string_field_free_memory(reg);
433         ast_free(reg);
434
435         /* ---Test reg 8, remove transport --- */
436         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
437                 goto alloc_fail;
438         } else if (
439             sip_parse_register_line(reg, reg8, 1) ||
440                 strcmp(reg->callback, "extension")           ||
441                 strcmp(reg->username, "name@namedomain") ||
442                 strcmp(reg->hostname, "domain")     ||
443                 strcmp(reg->authuser, "authuser")           ||
444                 strcmp(reg->secret, "pass")         ||
445                 strcmp(reg->peername, "peer")           ||
446                 reg->transport != SIP_TRANSPORT_UDP ||
447                 reg->timeout != -1                  ||
448                 reg->expire != -1                   ||
449                 reg->refresh != 111 ||
450                 reg->expiry != 111 ||
451                 reg->configured_expiry != 111 ||
452                 reg->portno != 1234    ||
453                 reg->callid_valid != FALSE          ||
454                 reg->ocseq != INITIAL_CSEQ) {
455
456                 ast_str_append(&args->ast_test_error_str, 0, "Test 8, remove transport failed.\n");
457                 res = AST_TEST_FAIL;
458         }
459         ast_string_field_free_memory(reg);
460         ast_free(reg);
461
462         /* ---Test reg 9, missing domain, expected to fail --- */
463         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
464                 goto alloc_fail;
465         } else if (!sip_parse_register_line(reg, reg9, 1)) {
466
467                 ast_str_append(&args->ast_test_error_str, 0, "Test 9, missing domain, expected to fail but did not.\n");
468                 res = AST_TEST_FAIL;
469         }
470         ast_string_field_free_memory(reg);
471         ast_free(reg);
472
473         /* ---Test reg 10,  missing user, expected to fail --- */
474         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
475                 goto alloc_fail;
476         } else if (!sip_parse_register_line(reg, reg10, 1)) {
477
478                 ast_str_append(&args->ast_test_error_str, 0, "Test 10, missing user expected to fail but did not\n");
479                 res = AST_TEST_FAIL;
480         }
481         ast_string_field_free_memory(reg);
482         ast_free(reg);
483
484         /* ---Test reg 11, no registry object, expected to fail--- */
485         if (!sip_parse_register_line(NULL, reg1, 1)) {
486
487                 ast_str_append(&args->ast_test_error_str, 0, "Test 11, no registery object, expected to fail but did not.\n");
488                 res = AST_TEST_FAIL;
489         }
490
491         /* ---Test reg 11,  no registry line, expected to fail --- */
492         if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
493                 goto alloc_fail;
494         } else if (!sip_parse_register_line(reg, NULL, 1)) {
495
496                 ast_str_append(&args->ast_test_error_str, 0, "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_str_set(&args->ast_test_error_str, 0, "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
589                 ast_str_append(&args->ast_test_error_str, 0, "Test 1: simple host failed.\n");
590                 res = AST_TEST_FAIL;
591         }
592
593         /* test 2, add tcp transport */
594         sip_parse_host(host2, 1, &host, &port, &transport);
595         if (port != STANDARD_SIP_PORT ||
596                 ast_strlen_zero(host) || strcmp(host, "www.blah.com") ||
597                 transport != SIP_TRANSPORT_TCP) {
598
599                 ast_str_append(&args->ast_test_error_str, 0, "Test 2: tcp host failed.\n");
600                 res = AST_TEST_FAIL;
601         }
602
603         /* test 3, add tls transport */
604         sip_parse_host(host3, 1, &host, &port, &transport);
605         if (port != STANDARD_TLS_PORT ||
606                 ast_strlen_zero(host) || strcmp(host, "10.10.10.10") ||
607                 transport != SIP_TRANSPORT_TLS) {
608
609                 ast_str_append(&args->ast_test_error_str, 0, "Test 3: tls host failed. \n");
610                 res = AST_TEST_FAIL;
611         }
612
613         /* test 4, add custom port with tls */
614         sip_parse_host(host4, 1, &host, &port, &transport);
615         if (port != 1234 ||
616                 ast_strlen_zero(host) || strcmp(host, "10.10.10.10") ||
617                 transport != SIP_TRANSPORT_TLS) {
618
619                 ast_str_append(&args->ast_test_error_str, 0, "Test 4: tls host with custom port failed.\n");
620                 res = AST_TEST_FAIL;
621         }
622
623         /* test 5, simple host with custom port */
624         sip_parse_host(host5, 1, &host, &port, &transport);
625         if (port != 1234 ||
626                 ast_strlen_zero(host) || strcmp(host, "10.10.10.10") ||
627                 transport != SIP_TRANSPORT_UDP) {
628
629                 ast_str_append(&args->ast_test_error_str, 0, "Test 5: simple host with custom port failed.\n");
630                 res = AST_TEST_FAIL;
631         }
632         return res;
633
634         /* test 6, expected failure with NULL input */
635         if (sip_parse_host(NULL, 1, &host, &port, &transport)) {
636
637                 ast_str_append(&args->ast_test_error_str, 0, "Test 6: expected error on NULL input did not occur.\n");
638                 res = AST_TEST_FAIL;
639         }
640         return res;
641
642 }
643
644 /*! \brief SIP test registration */
645 void sip_config_parser_register_tests(void)
646 {
647         AST_TEST_REGISTER(sip_parse_register_line_test);
648         AST_TEST_REGISTER(sip_parse_host_line_test);
649 }
650
651 /*! \brief SIP test registration */
652 void sip_config_parser_unregister_tests(void)
653 {
654         AST_TEST_UNREGISTER(sip_parse_register_line_test);
655         AST_TEST_UNREGISTER(sip_parse_host_line_test);
656 }
657