1 /*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2006 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25 /**@CFILE tport_test.c
26 *
27 * Test functions for transports
28 *
29 * @internal
30 *
31 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
32 *
33 * @date Created: Wed Apr 3 11:25:13 2002 ppessi
34 */
35
36 /* always assert()s */
37 #undef NDEBUG
38
39 #include "config.h"
40
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <limits.h>
45 #include <stdio.h>
46 #include <assert.h>
47
48 typedef struct tp_test_s tp_test_t;
49
50 #define TP_STACK_T tp_test_t
51 #define TP_CLIENT_T struct called
52
53 #include <sofia-sip/su_wait.h>
54 #include <sofia-sip/su_md5.h>
55
56 #include "tport_internal.h" /* Get SU_DEBUG_*() */
57
58 #include "test_class.h"
59 #include "test_protos.h"
60 #include "sofia-sip/msg.h"
61 #include "sofia-sip/msg_mclass.h"
62 #include "sofia-sip/msg_addr.h"
63
64 #if HAVE_SIGCOMP
65 #include <sigcomp.h>
66 #endif
67
68 #include <sofia-sip/base64.h>
69
70 #include <sofia-sip/su_log.h>
71
72 #include "sofia-sip/tport.h"
73
74 struct tp_test_s {
75 su_home_t tt_home[1];
76 int tt_flags;
77 su_root_t *tt_root;
78 msg_mclass_t *tt_mclass;
79 tport_t *tt_srv_tports;
80 tport_t *tt_tports;
81
82 tport_t *tt_rtport;
83
84 tp_name_t tt_udp_name[1];
85 tp_name_t tt_udp_comp[1];
86
87 tp_name_t tt_tcp_name[1];
88 tp_name_t tt_tcp_comp[1];
89
90 tp_name_t tt_sctp_name[1];
91 tp_name_t tt_sctp_comp[1];
92
93 tp_name_t tt_tls_name[1];
94 tp_name_t tt_tls_comp[1];
95
96 #if HAVE_SIGCOMP
97 struct sigcomp_state_handler *state_handler;
98 struct sigcomp_algorithm const *algorithm;
99 struct sigcomp_compartment *master_cc;
100
101 #define IF_SIGCOMP_TPTAG_COMPARTMENT(cc) TAG_IF(cc, TPTAG_COMPARTMENT(cc)),
102 #else
103 #define IF_SIGCOMP_TPTAG_COMPARTMENT(cc)
104 #endif
105
106 int tt_status;
107 int tt_received;
108 msg_t *tt_rmsg;
109 uint8_t tt_digest[SU_MD5_DIGEST_SIZE];
110
111 su_addrinfo_t const *tt_tcp_addr;
112 tport_t *tt_tcp;
113 };
114
115 int tstflags;
116 #define TSTFLAGS tstflags
117
118 #include <sofia-sip/tstdef.h>
119
120 char const name[] = "tport_test";
121
122 SOFIAPUBVAR su_log_t tport_log[];
123
name_test(tp_test_t * tt)124 static int name_test(tp_test_t *tt)
125 {
126 tp_name_t tpn[1];
127
128 su_home_t home[1] = { SU_HOME_INIT(home) };
129
130 su_sockaddr_t su[1];
131
132 BEGIN();
133
134 memset(su, 0, sizeof su);
135
136 su->su_port = htons(5060);
137 su->su_family = AF_INET;
138
139 TEST(tport_convert_addr(home, tpn, "tcp", "localhost", su), 0);
140
141 su->su_family = AF_INET;
142
143 TEST(tport_convert_addr(home, tpn, "tcp", "localhost", su), 0);
144
145 #if SU_HAVE_IN6
146 su->su_family = AF_INET6;
147 TEST(tport_convert_addr(home, tpn, "tcp", "localhost", su), 0);
148 #endif
149
150 END();
151 }
152
153 /* Count number of transports in chain */
154 static
count_tports(tport_t * tp)155 int count_tports(tport_t *tp)
156 {
157 int n = 0;
158
159 for (tp = tport_primaries(tp); tp; tp = tport_next(tp))
160 n++;
161
162 return n;
163 }
164
check_msg(tp_test_t * tt,msg_t * msg,char const * ident)165 static int check_msg(tp_test_t *tt, msg_t *msg, char const *ident)
166 {
167 msg_test_t *tst;
168 msg_payload_t *pl;
169 usize_t i, len;
170
171 BEGIN();
172
173 TEST_1(tst = msg_test_public(msg));
174 TEST_1(pl = tst->msg_payload);
175
176 if (ident) {
177 if (!tst->msg_content_location ||
178 strcmp(ident, tst->msg_content_location->g_string))
179 return 1;
180 }
181
182 len = pl->pl_len;
183
184 for (i = 0; i < len; i++) {
185 if (pl->pl_data[i] != (char) (i % 240))
186 break;
187 }
188
189 if (pl)
190 return i != len;
191
192 END();
193 }
194
test_create_md5(tp_test_t * tt,msg_t * msg)195 static int test_create_md5(tp_test_t *tt, msg_t *msg)
196 {
197 msg_test_t *tst;
198 msg_payload_t *pl;
199 su_md5_t md5[1];
200
201 BEGIN();
202
203 TEST_1(tst = msg_test_public(msg));
204 TEST_1(pl = tst->msg_payload);
205
206 su_md5_init(md5);
207 su_md5_update(md5, pl->pl_data, pl->pl_len);
208 su_md5_digest(md5, tt->tt_digest);
209
210 END();
211 }
212
test_check_md5(tp_test_t * tt,msg_t * msg)213 static int test_check_md5(tp_test_t *tt, msg_t *msg)
214 {
215 msg_test_t *tst;
216 msg_payload_t *pl;
217 su_md5_t md5[1];
218 uint8_t digest[SU_MD5_DIGEST_SIZE];
219
220 BEGIN();
221
222 TEST_1(tst = msg_test_public(msg));
223 TEST_1(pl = tst->msg_payload);
224
225 su_md5_init(md5);
226 su_md5_update(md5, pl->pl_data, pl->pl_len);
227 su_md5_digest(md5, digest);
228
229 TEST(memcmp(digest, tt->tt_digest, sizeof digest), 0);
230
231 END();
232 }
233
test_msg_md5(tp_test_t * tt,msg_t * msg)234 static int test_msg_md5(tp_test_t *tt, msg_t *msg)
235 {
236 msg_test_t *tst;
237
238 BEGIN();
239
240 TEST_1(tst = msg_test_public(msg));
241
242 if (tst->msg_content_md5) {
243 su_md5_t md5sum[1];
244 uint8_t digest[SU_MD5_DIGEST_SIZE];
245 char b64[BASE64_SIZE(SU_MD5_DIGEST_SIZE) + 1];
246
247 msg_payload_t *pl =tst->msg_payload;
248
249 su_md5_init(md5sum);
250 su_md5_update(md5sum, pl->pl_data, pl->pl_len);
251 su_md5_digest(md5sum, digest);
252
253 base64_e(b64, sizeof(b64), digest, sizeof(digest));
254
255 if (strcmp(b64, tst->msg_content_md5->g_string)) {
256 ;
257 }
258
259 TEST_S(b64, tst->msg_content_md5->g_string);
260 } else {
261 TEST_1(tst->msg_content_md5);
262 }
263
264 END();
265 }
266
267 #define TPORT_TEST_VERSION MSG_TEST_VERSION_CURRENT
268
new_test_msg(tp_test_t * tt,msg_t ** retval,char const * ident,int N,int len)269 static int new_test_msg(tp_test_t *tt, msg_t **retval,
270 char const *ident,
271 int N, int len)
272 {
273 msg_t *msg;
274 msg_test_t *tst;
275 su_home_t *home;
276 msg_request_t *rq;
277 msg_unknown_t *u;
278 msg_content_location_t *cl;
279 msg_content_md5_t *md5;
280 msg_content_length_t *l;
281 msg_separator_t *sep;
282 msg_payload_t payload[1];
283 msg_header_t *h;
284 int i;
285
286 su_md5_t md5sum[1];
287 uint8_t digest[SU_MD5_DIGEST_SIZE];
288 char b64[BASE64_SIZE(SU_MD5_DIGEST_SIZE) + 1];
289
290 BEGIN();
291
292 TEST_1(msg = msg_create(tt->tt_mclass, 0));
293 TEST_1(tst = msg_test_public(msg));
294 TEST_1(home = msg_home(msg));
295
296 TEST_SIZE(msg_maxsize(msg, 1024 + N * len), 0);
297
298 TEST_1(rq = msg_request_make(home, "DO im:foo@faa " TPORT_TEST_VERSION));
299 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)rq), 0);
300
301 TEST_1(u = msg_unknown_make(home, "Foo: faa"));
302 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)u), 0);
303
304 TEST_1(u = msg_unknown_make(home, "Foo: faa"));
305 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)u), 0);
306
307 if (ident) {
308 TEST_1(cl = msg_content_location_make(home, ident));
309 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)cl), 0);
310 }
311
312 msg_payload_init(payload);
313
314 payload->pl_len = len;
315 TEST_1(payload->pl_data = su_zalloc(home, payload->pl_len));
316
317 for (i = 0; i < len; i++) {
318 payload->pl_data[i] = (char) (i % 240);
319 }
320
321 su_md5_init(md5sum);
322
323 for (i = 0; i < N; i++) {
324 h = msg_header_dup(home, (msg_header_t*)payload);
325 TEST_1(h);
326 TEST(msg_header_insert(msg, (void *)tst, h), 0);
327 su_md5_update(md5sum, payload->pl_data, payload->pl_len);
328 }
329
330 TEST_1(l = msg_content_length_format(home, MOD_ZU, (size_t)(N * payload->pl_len)));
331 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)l), 0);
332
333 su_md5_digest(md5sum, digest);
334
335 base64_e(b64, sizeof(b64), digest, sizeof(digest));
336
337 TEST_1(md5 = msg_content_md5_make(home, b64));
338 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)md5), 0);
339
340 TEST_1(sep = msg_separator_create(home));
341 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)sep), 0);
342
343 TEST(msg_serialize(msg, (void *)tst), 0);
344
345 *retval = msg;
346
347 END();
348 }
349
350 static
351 struct sigcomp_compartment *
352 test_sigcomp_compartment(tp_test_t *tt, tport_t *tp, tp_name_t const *tpn);
353
tp_test_recv(tp_test_t * tt,tport_t * tp,msg_t * msg,tp_magic_t * magic,su_time_t now)354 static void tp_test_recv(tp_test_t *tt,
355 tport_t *tp,
356 msg_t *msg,
357 tp_magic_t *magic,
358 su_time_t now)
359 {
360 tp_name_t frm[1];
361
362 if (tport_delivered_from(tp, msg, frm) != -1 && frm->tpn_comp) {
363 struct sigcomp_compartment *cc = test_sigcomp_compartment(tt, tp, frm);
364
365 tport_sigcomp_accept(tp, cc, msg);
366 }
367
368 tt->tt_status = 1;
369 tt->tt_received++;
370
371 if (msg_has_error(msg)) {
372 tt->tt_status = -1;
373 tt->tt_rtport = tp;
374 }
375 else if (test_msg_md5(tt, msg))
376 msg_destroy(msg);
377 else if (tt->tt_rmsg)
378 msg_destroy(msg);
379 else {
380 tt->tt_rmsg = msg;
381 tt->tt_rtport = tp;
382 }
383 }
384
tp_test_error(tp_test_t * tt,tport_t * tp,int errcode,char const * remote)385 static void tp_test_error(tp_test_t *tt,
386 tport_t *tp,
387 int errcode,
388 char const *remote)
389 {
390 tt->tt_status = -1;
391 fprintf(stderr, "tp_test_error(%p): error %d (%s) from %s\n",
392 (void *)tp, errcode, su_strerror(errcode),
393 remote ? remote : "<unknown destination>");
394 }
395
tp_test_msg(tp_test_t * tt,int flags,char const data[],usize_t size,tport_t const * tp,tp_client_t * tpc)396 msg_t *tp_test_msg(tp_test_t *tt, int flags,
397 char const data[], usize_t size,
398 tport_t const *tp,
399 tp_client_t *tpc)
400 {
401 msg_t *msg = msg_create(tt->tt_mclass, flags);
402
403 msg_maxsize(msg, 2 * 1024 * 1024);
404
405 return msg;
406 }
407
408
409 static
410 struct sigcomp_compartment *
test_sigcomp_compartment(tp_test_t * tt,tport_t * tp,tp_name_t const * tpn)411 test_sigcomp_compartment(tp_test_t *tt,
412 tport_t *tp,
413 tp_name_t const *tpn)
414 {
415 struct sigcomp_compartment *cc = NULL;
416 #if HAVE_SIGCOMP
417 char name[256];
418 int namesize;
419
420 namesize = snprintf(name, sizeof name, "TEST_%s/%s:%s",
421 tpn->tpn_proto,
422 tpn->tpn_host,
423 tpn->tpn_port);
424
425 if (namesize <= 0 || namesize >= sizeof name)
426 return NULL;
427
428 cc = sigcomp_compartment_access(tt->state_handler,
429 0, name, namesize, NULL, 0);
430
431 if (cc == NULL) {
432 cc = sigcomp_compartment_create(tt->algorithm, tt->state_handler,
433 0, name, namesize, NULL, 0);
434
435 sigcomp_compartment_option(cc, "dms=32768");
436 }
437 #endif
438
439 return cc;
440 }
441
442 /* Accept/reject early SigComp message */
test_sigcomp_accept(tp_stack_t * tt,tport_t * tp,msg_t * msg)443 int test_sigcomp_accept(tp_stack_t *tt, tport_t *tp, msg_t *msg)
444 {
445 struct sigcomp_compartment *cc = NULL;
446
447 cc = test_sigcomp_compartment(tt, tp, tport_name(tp));
448
449 if (cc)
450 tport_sigcomp_assign(tp, cc);
451
452 return tport_sigcomp_accept(tp, cc, msg);
453 }
454
455
456 tp_stack_class_t const tp_test_class[1] =
457 {{
458 /* tpac_size */ sizeof(tp_test_class),
459 /* tpac_recv */ tp_test_recv,
460 /* tpac_error */ tp_test_error,
461 /* tpac_alloc */ tp_test_msg,
462 }};
463
init_test(tp_test_t * tt)464 static int init_test(tp_test_t *tt)
465 {
466 tp_name_t myname[1] = {{ "*", "*", "*", "*", "sigcomp" }};
467 #if HAVE_SCTP
468 char const * transports[] = { "udp", "tcp", "sctp", NULL };
469 #else
470 char const * transports[] = { "udp", "tcp", NULL };
471 #endif
472 tp_name_t const *tpn;
473 tport_t *tp;
474 unsigned idle;
475 int logging = -1;
476
477 BEGIN();
478
479 int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST;
480
481 #ifdef AI_ALL
482 mask |= AI_ALL;
483 #endif
484 #ifdef AI_V4MAPPED_CFG
485 mask |= AI_V4MAPPED_CFG;
486 #endif
487 #ifdef AI_ADDRCONFIG
488 mask |= AI_ADDRCONFIG;
489 #endif
490 #ifdef AI_V4MAPPED
491 mask |= AI_V4MAPPED;
492 #endif
493
494 /* Test that we have no common flags with underlying getaddrinfo() */
495 TEST(mask & TP_AI_MASK, 0);
496
497 TEST_1(tt->tt_root = su_root_create(NULL));
498
499 myname->tpn_host = "127.0.0.1";
500 myname->tpn_ident = "client";
501
502 /* Create message class */
503 TEST_1(tt->tt_mclass = msg_mclass_clone(msg_test_mclass, 0, 0));
504
505 /* Try to insert Content-Length header (expecting failure) */
506 TEST(msg_mclass_insert(tt->tt_mclass, msg_content_length_href), -1);
507
508 #if HAVE_SIGCOMP
509 TEST_1(tt->state_handler = sigcomp_state_handler_create());
510 TEST_1(tt->algorithm =
511 sigcomp_algorithm_by_name(getenv("SIGCOMP_ALGORITHM")));
512 TEST_1(tt->master_cc =
513 sigcomp_compartment_create(tt->algorithm, tt->state_handler,
514 0, "", 0, NULL, 0));
515 TEST(sigcomp_compartment_option(tt->master_cc, "stateless"), 1);
516 #endif
517
518 /* Create client transport */
519 TEST_1(tt->tt_tports =
520 tport_tcreate(tt, tp_test_class, tt->tt_root,
521 IF_SIGCOMP_TPTAG_COMPARTMENT(tt->master_cc)
522 TAG_END()));
523
524 /* Bind client transports */
525 TEST(tport_tbind(tt->tt_tports, myname, transports,
526 TPTAG_SERVER(0), TAG_END()),
527 0);
528
529 if (getenv("TPORT_TEST_HOST"))
530 myname->tpn_host = getenv("TPORT_TEST_HOST");
531 else
532 myname->tpn_host = "*";
533
534 if (getenv("TPORT_TEST_PORT"))
535 myname->tpn_port = getenv("TPORT_TEST_PORT");
536
537 myname->tpn_ident = "server";
538
539 /* Create server transport */
540 TEST_1(tt->tt_srv_tports =
541 tport_tcreate(tt, tp_test_class, tt->tt_root,
542 IF_SIGCOMP_TPTAG_COMPARTMENT(tt->master_cc)
543 TAG_END()));
544
545 /* Bind server transports */
546 TEST(tport_tbind(tt->tt_srv_tports, myname, transports,
547 TPTAG_SERVER(1),
548 TAG_END()),
549 0);
550
551 /* Check that the master transport has idle parameter */
552 TEST(tport_get_params(tt->tt_srv_tports,
553 TPTAG_IDLE_REF(idle),
554 TAG_END()), 1);
555
556 /* Check that logging tag works */
557 TEST(tport_get_params(tt->tt_srv_tports,
558 TPTAG_LOG_REF(logging),
559 TAG_END()), 1);
560 TEST(tport_set_params(tt->tt_srv_tports,
561 TPTAG_LOG(logging),
562 TAG_END()), 1);
563
564
565 for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp))
566 TEST_S(tport_name(tp)->tpn_ident, "server");
567
568 {
569 su_sockaddr_t su[1];
570 socklen_t sulen;
571 int s;
572 int i, before, after;
573 char port[8];
574
575 tp_name_t rname[1];
576
577 *rname = *myname;
578
579 /* Check that we cannot bind to an already used socket */
580
581 memset(su, 0, sulen = sizeof(su->su_sin));
582 s = su_socket(su->su_family = AF_INET, SOCK_STREAM, 0); TEST_1(s != -1);
583 TEST_1(bind(s, &su->su_sa, sulen) != -1);
584 TEST_1(listen(s, 5) != -1);
585 TEST_1(getsockname(s, &su->su_sa, &sulen) != -1);
586
587 sprintf(port, "%u", ntohs(su->su_port));
588
589 rname->tpn_port = port;
590 rname->tpn_ident = "failure";
591
592 before = count_tports(tt->tt_srv_tports);
593
594 /* Bind server transports to an reserved port - this should fail */
595 TEST(tport_tbind(tt->tt_srv_tports, rname, transports,
596 TPTAG_SERVER(1),
597 TAG_END()),
598 -1);
599
600 after = count_tports(tt->tt_srv_tports);
601
602 /* Check that no new primary transports has been added by failed call */
603 TEST(before, after);
604
605 /* Add new transports to an ephemeral port with new identity */
606
607 for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp))
608 TEST_S(tport_name(tp)->tpn_ident, "server");
609
610 rname->tpn_port = "*";
611 rname->tpn_ident = "server2";
612
613 /* Bind server transports to another port */
614 TEST(tport_tbind(tt->tt_srv_tports, rname, transports,
615 TPTAG_SERVER(1),
616 TAG_END()),
617 0);
618
619 /* Check that new transports are after old ones. */
620 for (i = 0, tp = tport_primaries(tt->tt_srv_tports);
621 i < before;
622 i++, tp = tport_next(tp))
623 TEST_S(tport_name(tp)->tpn_ident, "server");
624
625 for (; tp; tp = tport_next(tp))
626 TEST_S(tport_name(tp)->tpn_ident, "server2");
627 }
628
629 #if HAVE_TLS
630 {
631 tp_name_t tlsname[1] = {{ "tls", "*", "*", "*", NULL }};
632 char const * transports[] = { "tls", NULL };
633
634 char const *srcdir = getenv("srcdir");
635
636 if (srcdir == NULL)
637 srcdir = ".";
638
639 tlsname->tpn_host = myname->tpn_host;
640 tlsname->tpn_ident = "server";
641
642 /* Bind client transports */
643 TEST(tport_tbind(tt->tt_tports, tlsname, transports,
644 TPTAG_SERVER(0),
645 TPTAG_CERTIFICATE(srcdir),
646 TAG_END()),
647 0);
648
649 /* Bind tls server transport */
650 TEST(tport_tbind(tt->tt_srv_tports, tlsname, transports,
651 TPTAG_SERVER(1),
652 TPTAG_CERTIFICATE(srcdir),
653 TAG_END()),
654 0);
655 }
656 #endif
657
658 for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp)) {
659 TEST_1(tpn = tport_name(tp));
660
661 if (tt->tt_flags & tst_verbatim) {
662 char const *host = tpn->tpn_host != tpn->tpn_canon ? tpn->tpn_host : "";
663 printf("bound transport to %s/%s:%s%s%s%s%s\n",
664 tpn->tpn_proto, tpn->tpn_canon, tpn->tpn_port,
665 host[0] ? ";maddr=" : "", host,
666 tpn->tpn_comp ? ";comp=" : "",
667 tpn->tpn_comp ? tpn->tpn_comp : "");
668 }
669
670 /* Ignore server2 tports for now */
671 if (strcmp(tpn->tpn_ident, "server"))
672 continue;
673
674 if (strcmp(tpn->tpn_proto, "udp") == 0) {
675 *tt->tt_udp_name = *tpn;
676 tt->tt_udp_name->tpn_comp = NULL;
677 tt->tt_udp_name->tpn_ident = NULL;
678 *tt->tt_udp_comp = *tpn;
679 tt->tt_udp_comp->tpn_ident = NULL;
680 }
681 else if (strcmp(tpn->tpn_proto, "tcp") == 0) {
682 *tt->tt_tcp_name = *tpn;
683 tt->tt_tcp_name->tpn_comp = NULL;
684 tt->tt_tcp_name->tpn_ident = NULL;
685 *tt->tt_tcp_comp = *tpn;
686 tt->tt_tcp_comp->tpn_ident = NULL;
687
688 if (tt->tt_tcp_addr == NULL) {
689 tt->tt_tcp_addr = tport_get_address(tp);
690 tt->tt_tcp = tp;
691 }
692 }
693 else if (strcmp(tpn->tpn_proto, "sctp") == 0) {
694 *tt->tt_sctp_name = *tpn;
695 tt->tt_sctp_name->tpn_ident = NULL;
696 }
697 else if (strcmp(tpn->tpn_proto, "tls") == 0) {
698 *tt->tt_tls_name = *tpn;
699 tt->tt_tls_name->tpn_ident = NULL;
700 }
701 }
702
703 END();
704 }
705
706 char const payload[] =
707 "Some data\n"
708 "More data\n";
709
710 #include <time.h>
711
712 int
tport_test_run(tp_test_t * tt,unsigned timeout)713 tport_test_run(tp_test_t *tt, unsigned timeout)
714 {
715 time_t now = time(NULL);
716
717 tt->tt_status = 0;
718
719 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
720 tt->tt_rtport = NULL;
721
722 while (!tt->tt_status) {
723 if (tt->tt_flags & tst_verbatim) {
724 fputs(".", stdout); fflush(stdout);
725 }
726 su_root_step(tt->tt_root, 500L);
727
728 if (!getenv("TPORT_TEST_DEBUG") &&
729 time(NULL) > (time_t)(now + timeout))
730 return 0;
731 }
732
733 return tt->tt_status;
734 }
735
udp_test(tp_test_t * tt)736 static int udp_test(tp_test_t *tt)
737 {
738 tport_t *tp;
739 msg_t *msg;
740 msg_test_t *tst;
741 su_home_t *home;
742 msg_request_t *rq;
743 msg_unknown_t *u;
744 msg_content_length_t *l;
745 msg_content_md5_t *md5;
746 msg_separator_t *sep;
747 msg_payload_t *pl;
748
749 BEGIN();
750
751 TEST_1(msg = msg_create(tt->tt_mclass, 0));
752 TEST_1(tst = msg_test_public(msg));
753 TEST_1(home = msg_home(msg));
754
755 TEST_1(rq = msg_request_make(home, "DO im:foo@faa " TPORT_TEST_VERSION));
756 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)rq), 0);
757
758 TEST_1(u = msg_unknown_make(home, "Foo: faa"));
759 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)u), 0);
760
761 TEST_1(pl = msg_payload_make(home, payload));
762 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)pl), 0);
763
764 TEST_1(l = msg_content_length_format(home, MOD_ZU, (size_t)pl->pl_len));
765 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)l), 0);
766
767 TEST_1(md5 = msg_content_md5_make(home, "R6nitdrtJFpxYzrPaSXfrA=="));
768 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)md5), 0);
769
770 TEST_1(sep = msg_separator_create(home));
771 TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)sep), 0);
772
773 TEST(msg_serialize(msg, (void *)tst), 0);
774
775 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_udp_name, TAG_END()));
776
777 TEST_S(tport_name(tp)->tpn_ident, "client");
778
779 TEST(tport_test_run(tt, 5), 1);
780
781 msg_destroy(msg);
782
783 #if 0
784 tp_name_t tpn[1] = {{ NULL }};
785
786 TEST_1(msg = tt->tt_rmsg); tt->tt_rmsg = NULL;
787
788 TEST_1(home = msg_home(msg));
789
790 TEST_1(tport_convert_addr(home, tpn, "udp", NULL, msg_addr(msg)) == 0);
791
792 tpn->tpn_comp = tport_name(tt->tt_rtport)->tpn_comp;
793
794 /* reply */
795 TEST_1(tport_tsend(tt->tt_rtport, msg, tpn, TAG_END()) != NULL);
796
797 msg_destroy(msg);
798
799 TEST(tport_test_run(tt, 5), 1);
800
801 msg_destroy(msg);
802 #endif
803
804 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
805
806 END();
807 }
808
809 int pending_server_close, pending_client_close;
810
server_closed_callback(tp_stack_t * tt,tp_client_t * client,tport_t * tp,msg_t * msg,int error)811 void server_closed_callback(tp_stack_t *tt, tp_client_t *client,
812 tport_t *tp, msg_t *msg, int error)
813 {
814 assert(msg == NULL);
815 assert(client == NULL);
816 if (msg == NULL) {
817 tport_release(tp, pending_server_close, NULL, NULL, client, 0);
818 pending_server_close = 0;
819 }
820 }
821
client_closed_callback(tp_stack_t * tt,tp_client_t * client,tport_t * tp,msg_t * msg,int error)822 void client_closed_callback(tp_stack_t *tt, tp_client_t *client,
823 tport_t *tp, msg_t *msg, int error)
824 {
825 assert(msg == NULL);
826 assert(client == NULL);
827 if (msg == NULL) {
828 tport_release(tp, pending_client_close, NULL, NULL, client, 0);
829 pending_client_close = 0;
830 }
831 }
832
tcp_test(tp_test_t * tt)833 static int tcp_test(tp_test_t *tt)
834 {
835 BEGIN();
836
837 msg_t *msg = NULL;
838 int i, N;
839 tport_t *tp, *tp0;
840 char ident[16];
841 su_time_t started;
842
843 /* Send a single message */
844 TEST_1(!new_test_msg(tt, &msg, "tcp-first", 1, 1024));
845 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
846 TEST_S(tport_name(tp)->tpn_ident, "client");
847 tp0 = tport_incref(tp);
848 msg_destroy(msg);
849
850 tport_set_params(tp,
851 TPTAG_KEEPALIVE(100),
852 TPTAG_PINGPONG(500),
853 TPTAG_IDLE(500),
854 TAG_END());
855
856 TEST(tport_test_run(tt, 5), 1);
857 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-first"));
858 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
859
860 /* Ask for notification upon close */
861 pending_client_close = tport_pend(tp0, NULL, client_closed_callback, NULL);
862 TEST_1(pending_client_close > 0);
863 tp = tt->tt_rtport;
864 pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
865 TEST_1(pending_server_close > 0);
866
867 N = 0; tt->tt_received = 0;
868
869 #ifndef WIN32 /* Windows seems to be buffering too much */
870
871 /* Create a large message, just to force queueing in sending end */
872 TEST(new_test_msg(tt, &msg, "tcp-0", 1, 16 * 64 * 1024), 0);
873 test_create_md5(tt, msg);
874 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
875 N++;
876 TEST_S(tport_name(tp)->tpn_ident, "client");
877 TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
878 msg_destroy(msg);
879
880 /* Fill up the queue */
881 for (i = 1; i < TPORT_QUEUESIZE; i++) {
882 snprintf(ident, sizeof ident, "tcp-%u", i);
883
884 TEST(new_test_msg(tt, &msg, ident, 1, 64 * 1024), 0);
885 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
886 N++;
887 TEST_S(tport_name(tp)->tpn_ident, "client");
888 TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
889 msg_destroy(msg);
890 }
891
892 /* This overflows the queue */
893 TEST(new_test_msg(tt, &msg, "tcp-overflow", 1, 1024), 0);
894 TEST_1(!tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
895 msg_destroy(msg);
896
897 TEST(tport_test_run(tt, 60), 1);
898 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-0"));
899 test_check_md5(tt, tt->tt_rmsg);
900 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
901
902 if (tt->tt_received < TPORT_QUEUESIZE) { /* We have not received it all */
903 snprintf(ident, sizeof ident, "tcp-%u", tt->tt_received);
904 TEST(tport_test_run(tt, 5), 1);
905 TEST_1(!check_msg(tt, tt->tt_rmsg, ident));
906 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
907 }
908 #else
909 (void)i; (void)ident;
910 #endif
911
912 /* This uses a new connection */
913 TEST_1(!new_test_msg(tt, &msg, "tcp-no-reuse", 1, 1024));
914 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
915 TPTAG_REUSE(0), TAG_END()));
916 N++;
917 TEST_S(tport_name(tp)->tpn_ident, "client");
918 TEST_1(tport_incref(tp) != tp0); tport_decref(&tp);
919 msg_destroy(msg);
920
921 /* This uses the old connection */
922 TEST_1(!new_test_msg(tt, &msg, "tcp-reuse", 1, 1024));
923 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
924 TPTAG_REUSE(1), TAG_END()));
925 N++;
926 TEST_S(tport_name(tp)->tpn_ident, "client");
927 TEST_1(tport_incref(tp) == tp0); tport_decref(&tp);
928 msg_destroy(msg);
929
930 /* Receive every message from queue */
931 while (tt->tt_received < N) {
932 TEST(tport_test_run(tt, 5), 1);
933 /* Validate message */
934 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
935 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
936 }
937
938 /* Try to send a single message */
939 TEST_1(!new_test_msg(tt, &msg, "tcp-last", 1, 1024));
940 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
941 TEST_S(tport_name(tp)->tpn_ident, "client");
942 TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
943 msg_destroy(msg);
944
945 TEST(tport_test_run(tt, 5), 1);
946
947 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-last"));
948 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
949
950 TEST_1(pending_server_close && pending_client_close);
951 SU_DEBUG_3(("tport_test(%p): waiting for PONG timeout\n", (void *)tp0));
952
953 /* Wait until notifications -
954 client closes when no pong is received and notifys pending,
955 then server closes and notifys pending */
956 while (pending_server_close || pending_client_close)
957 su_root_step(tt->tt_root, 50);
958
959 tport_decref(&tp0);
960
961 /* Again a single message */
962 TEST_1(!new_test_msg(tt, &msg, "tcp-pingpong", 1, 512));
963 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
964 TEST_S(tport_name(tp)->tpn_ident, "client");
965 tp0 = tport_incref(tp);
966 msg_destroy(msg);
967
968 tport_set_params(tp0,
969 TPTAG_KEEPALIVE(250),
970 TPTAG_PINGPONG(200),
971 TAG_END());
972
973 TEST(tport_test_run(tt, 5), 1);
974 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-pingpong"));
975 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
976
977 /* Ask for notifications upon close */
978 pending_client_close = tport_pend(tp0, NULL, client_closed_callback, NULL);
979 TEST_1(pending_client_close > 0);
980
981 tp = tt->tt_rtport;
982 pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
983 TEST_1(pending_server_close > 0);
984
985 /* Now server responds with pong ... */
986 TEST(tport_set_params(tp, TPTAG_PONG2PING(1), TAG_END()), 1);
987
988 started = su_now();
989
990 while (pending_server_close && pending_client_close) {
991 su_root_step(tt->tt_root, 50);
992 if (su_duration(su_now(), started) > 1000)
993 break;
994 }
995
996 /* ... and we are still pending after a second */
997 TEST_1(pending_client_close && pending_server_close);
998 TEST_1(su_duration(su_now(), started) > 1000);
999
1000 tport_shutdown(tp0, 2);
1001 tport_unref(tp0);
1002
1003 while (pending_server_close || pending_client_close)
1004 su_root_step(tt->tt_root, 50);
1005
1006 END();
1007 }
1008
test_incomplete(tp_test_t * tt)1009 static int test_incomplete(tp_test_t *tt)
1010 {
1011 BEGIN();
1012
1013 su_addrinfo_t const *ai = tt->tt_tcp_addr;
1014 su_socket_t s;
1015 int connected;
1016
1017 TEST_1(ai != NULL);
1018
1019 TEST(tport_set_params(tt->tt_tcp, TPTAG_TIMEOUT(500), TAG_END()), 1);
1020
1021 s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1022 TEST_1(s != SOCKET_ERROR);
1023
1024 su_setblocking(s, 1);
1025 connected = connect(s, ai->ai_addr, (socklen_t)ai->ai_addrlen);
1026
1027 su_root_step(tt->tt_root, 50);
1028
1029 TEST(su_send(s, "F", 1, 0), 1);
1030 su_root_step(tt->tt_root, 50);
1031 TEST(su_send(s, "O", 1, 0), 1);
1032 su_root_step(tt->tt_root, 50);
1033 TEST(su_send(s, "O", 1, 0), 1);
1034 su_root_step(tt->tt_root, 50);
1035 TEST(su_send(s, " ", 1, 0), 1);
1036 su_root_step(tt->tt_root, 50);
1037
1038 tt->tt_received = 0;
1039 TEST(tport_test_run(tt, 5), -1);
1040 TEST(tt->tt_received, 1);
1041 TEST_P(tt->tt_rmsg, NULL);
1042
1043 su_close(s);
1044
1045 END();
1046 }
1047
reuse_test(tp_test_t * tt)1048 static int reuse_test(tp_test_t *tt)
1049 {
1050 msg_t *msg = NULL;
1051 int i, reuse = -1;
1052 tport_t *tp, *tp0, *tp1;
1053 tp_name_t tpn[1];
1054
1055 BEGIN();
1056
1057 /* Flush existing connections */
1058 *tpn = *tt->tt_tcp_name;
1059 tpn->tpn_port = "*";
1060 TEST_1(tp = tport_by_name(tt->tt_tports, tpn));
1061 TEST_1(tport_is_primary(tp));
1062 TEST(tport_flush(tp), 0);
1063
1064 for (i = 0; i < 10; i++)
1065 su_root_step(tt->tt_root, 10L);
1066
1067 TEST(tport_set_params(tp, TPTAG_REUSE(0), TAG_END()), 1);
1068
1069 /* Send two messages */
1070 TEST(new_test_msg(tt, &msg, "reuse-1", 1, 1024), 0);
1071 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
1072 TEST_S(tport_name(tp)->tpn_ident, "client");
1073 TEST_1(tp0 = tport_incref(tp));
1074 TEST(tport_get_params(tp, TPTAG_REUSE_REF(reuse), TAG_END()), 1);
1075 TEST(reuse, 0);
1076 msg_destroy(msg), msg = NULL;
1077
1078 TEST(new_test_msg(tt, &msg, "reuse-2", 1, 1024), 0);
1079 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
1080 TEST_S(tport_name(tp)->tpn_ident, "client");
1081 TEST_1(tp1 = tport_incref(tp)); TEST_1(tp0 != tp1);
1082 TEST(tport_get_params(tp, TPTAG_REUSE_REF(reuse), TAG_END()), 1);
1083 TEST(reuse, 0);
1084 msg_destroy(msg), msg = NULL;
1085
1086 /* Receive every message from queue */
1087 for (tt->tt_received = 0;
1088 tt->tt_received < 2;) {
1089 TEST(tport_test_run(tt, 5), 1);
1090 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1091 }
1092
1093 /* Enable reuse on single connection */
1094 TEST(tport_set_params(tp1, TPTAG_REUSE(1), TAG_END()), 1);
1095 TEST(new_test_msg(tt, &msg, "reuse-3", 1, 1024), 0);
1096 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
1097 TPTAG_REUSE(1),
1098 TAG_END()));
1099 TEST_S(tport_name(tp)->tpn_ident, "client");
1100 TEST_1(tp1 == tp);
1101 TEST(tport_get_params(tp, TPTAG_REUSE_REF(reuse), TAG_END()), 1);
1102 TEST(reuse, 1);
1103 msg_destroy(msg), msg = NULL;
1104
1105 TEST(tport_test_run(tt, 5), 1);
1106 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1107
1108 TEST_1(tp = tport_by_name(tt->tt_tports, tpn));
1109 TEST_1(tport_is_primary(tp));
1110 TEST(tport_set_params(tp, TPTAG_REUSE(1), TAG_END()), 1);
1111
1112 /* Send a single message with different connection */
1113 TEST_1(!new_test_msg(tt, &msg, "fresh-1", 1, 1024));
1114 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
1115 TPTAG_FRESH(1),
1116 TPTAG_REUSE(1),
1117 TAG_END()));
1118 TEST_S(tport_name(tp)->tpn_ident, "client");
1119 TEST_1(tport_incref(tp) != tp1); tport_decref(&tp);
1120 msg_destroy(msg);
1121
1122 TEST(tport_test_run(tt, 5), 1);
1123
1124 TEST_1(!check_msg(tt, tt->tt_rmsg, "fresh-1"));
1125 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1126
1127 TEST_1(tport_shutdown(tp0, 2) >= 0);
1128 TEST_1(tport_shutdown(tp1, 2) >= 0);
1129 TEST_1(tport_shutdown(tp0, 1) >= 0);
1130
1131 TEST(tport_shutdown(NULL, 0), -1);
1132
1133 tport_decref(&tp0);
1134 tport_decref(&tp1);
1135
1136 END();
1137 }
1138
sctp_test(tp_test_t * tt)1139 static int sctp_test(tp_test_t *tt)
1140 {
1141 BEGIN();
1142
1143 msg_t *msg = NULL;
1144 int i, n;
1145 tport_t *tp, *tp0;
1146 char buffer[32];
1147
1148 if (!tt->tt_sctp_name->tpn_proto)
1149 return 0;
1150
1151 /* Just a small and nice message first */
1152 TEST_1(!new_test_msg(tt, &msg, "cid:sctp-first", 1, 1024));
1153 test_create_md5(tt, msg);
1154 TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name, TAG_END()));
1155 TEST_S(tport_name(tp)->tpn_ident, "client");
1156 msg_destroy(msg);
1157
1158 tport_set_params(tp, TPTAG_KEEPALIVE(100), TPTAG_IDLE(500), TAG_END());
1159
1160 TEST(tport_test_run(tt, 5), 1);
1161
1162 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
1163 test_check_md5(tt, tt->tt_rmsg);
1164 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1165
1166 tp0 = tport_ref(tp);
1167
1168 pending_server_close = pending_client_close = 0;
1169
1170 /* Ask for notification upon close */
1171 pending_client_close = tport_pend(tp, NULL, client_closed_callback, NULL);
1172 TEST_1(pending_client_close > 0);
1173 tp = tt->tt_rtport;
1174 pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
1175 TEST_1(pending_server_close > 0);
1176
1177 if (0) { /* SCTP does not work reliably. Really. */
1178
1179 tt->tt_received = 0;
1180
1181 /* Create large messages, just to force queueing in sending end */
1182 for (n = 0; !tport_queuelen(tp); n++) {
1183 snprintf(buffer, sizeof buffer, "cid:sctp-%u", n);
1184 TEST_1(!new_test_msg(tt, &msg, buffer, 1, 32000));
1185 test_create_md5(tt, msg);
1186 TEST_1(tp = tport_tsend(tp0, msg, tt->tt_sctp_name, TAG_END()));
1187 TEST_S(tport_name(tp)->tpn_ident, "client");
1188 msg_destroy(msg);
1189 }
1190
1191 /* Fill up the queue */
1192 for (i = 1; i < TPORT_QUEUESIZE; i++) {
1193 snprintf(buffer, sizeof buffer, "cid:sctp-%u", n + i);
1194 TEST_1(!new_test_msg(tt, &msg, buffer, 1, 1024));
1195 TEST_1(tp = tport_tsend(tp0, msg, tt->tt_sctp_name, TAG_END()));
1196 msg_destroy(msg);
1197 }
1198
1199 /* Try to overflow the queue */
1200 snprintf(buffer, sizeof buffer, "cid:sctp-%u", n + i);
1201 TEST_1(!new_test_msg(tt, &msg, buffer, 1, 1024));
1202 TEST_1(!tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name, TAG_END()));
1203 msg_destroy(msg);
1204
1205 TEST(tport_test_run(tt, 5), 1);
1206
1207 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
1208 test_check_md5(tt, tt->tt_rmsg);
1209 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1210
1211 /* This uses a new connection */
1212 TEST_1(!new_test_msg(tt, &msg, "cid:sctp-new", 1, 1024));
1213 TEST_1(tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name,
1214 TPTAG_REUSE(0), TAG_END()));
1215 msg_destroy(msg);
1216
1217 /* Receive every message from queue */
1218 for (; tt->tt_received < n + TPORT_QUEUESIZE - 1;) {
1219 TEST(tport_test_run(tt, 10), 1);
1220 /* Validate message */
1221 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
1222 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1223 }
1224
1225 /* Try to send a single message */
1226 TEST_1(!new_test_msg(tt, &msg, "cid:sctp-final", 1, 512));
1227 TEST_1(tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name, TAG_END()));
1228 msg_destroy(msg);
1229
1230 TEST(tport_test_run(tt, 10), 1);
1231
1232 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
1233 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1234 }
1235
1236 tport_unref(tp0);
1237
1238 /* Wait until notifications -
1239 client closes when idle and notifys pending,
1240 then server closes and notifys pending */
1241 while (pending_server_close || pending_client_close)
1242 su_root_step(tt->tt_root, 50);
1243
1244 END();
1245 }
1246
1247 struct called {
1248 int n, error, pending, released;
1249 };
1250
1251 static
tls_error_callback(tp_stack_t * tt,tp_client_t * client,tport_t * tp,msg_t * msg,int error)1252 void tls_error_callback(tp_stack_t *tt, tp_client_t *client,
1253 tport_t *tp, msg_t *msg, int error)
1254 {
1255 struct called *called = (struct called *)client;
1256
1257 tt->tt_status = -1;
1258
1259 called->n++, called->error = error;
1260
1261 if (called->pending) {
1262 called->released = tport_release(tp, called->pending, msg, NULL, client, 0);
1263 called->pending = 0;
1264 }
1265 }
1266
tls_test(tp_test_t * tt)1267 static int tls_test(tp_test_t *tt)
1268 {
1269 BEGIN();
1270
1271 #if HAVE_TLS
1272 tp_name_t const *dst = tt->tt_tls_name;
1273 msg_t *msg = NULL;
1274 int i;
1275 char ident[16];
1276 tport_t *tp, *tp0;
1277 struct called called[1] = {{ 0, 0, 0, 0 }};
1278
1279 TEST_S(dst->tpn_proto, "tls");
1280
1281 /* Send a single message */
1282 TEST_1(!new_test_msg(tt, &msg, "tls-first", 1, 1024));
1283 TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
1284 TEST_1(tp0 = tport_ref(tp));
1285 TEST_1(called->pending = tport_pend(tp, msg, tls_error_callback, (tp_client_t *)called));
1286
1287 i = tport_test_run(tt, 5);
1288 msg_destroy(msg);
1289
1290 if (i < 0) {
1291 if (called->n) {
1292 TEST(called->released, 0);
1293 puts("test_tport: skipping TLS tests");
1294 tport_unref(tp0);
1295 return 0;
1296 }
1297 }
1298
1299 TEST(i, 1);
1300
1301 TEST_1(!check_msg(tt, tt->tt_rmsg, "tls-first"));
1302 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1303
1304 tport_set_params(tp, TPTAG_KEEPALIVE(100), TPTAG_IDLE(500), TAG_END());
1305
1306 /* Ask for notification upon close */
1307 pending_client_close = tport_pend(tp0, NULL, client_closed_callback, NULL);
1308 TEST_1(pending_client_close > 0);
1309 tp = tt->tt_rtport;
1310 pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
1311
1312 TEST_1(pending_server_close > 0);
1313
1314 /* Send a largish message */
1315 TEST_1(!new_test_msg(tt, &msg, "tls-0", 16, 16 * 1024));
1316 test_create_md5(tt, msg);
1317 TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
1318 TEST_1(tp == tp0);
1319 msg_destroy(msg);
1320
1321 /* Fill up the queue */
1322 for (i = 1; i < TPORT_QUEUESIZE; i++) {
1323 snprintf(ident, sizeof ident, "tls-%u", i);
1324
1325 TEST_1(!new_test_msg(tt, &msg, ident, 2, 512));
1326 TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
1327 TEST_1(tp == tp0);
1328 msg_destroy(msg);
1329 }
1330
1331 /* This uses a new connection */
1332 TEST_1(!new_test_msg(tt, &msg, "tls-no-reuse", 1, 1024));
1333 TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst,
1334 TPTAG_REUSE(0), TAG_END()));
1335 TEST_1(tp != tp0);
1336 msg_destroy(msg);
1337
1338 tt->tt_received = 0;
1339
1340 /* Receive every message from queue */
1341 while (tt->tt_received < TPORT_QUEUESIZE + 1) {
1342 TEST(tport_test_run(tt, 5), 1);
1343 /* Validate message */
1344 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1345 }
1346
1347 /* Try to send a single message */
1348 TEST_1(!new_test_msg(tt, &msg, "tls-last", 1, 1024));
1349 TEST_1(tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
1350 msg_destroy(msg);
1351
1352 TEST(tport_test_run(tt, 5), 1);
1353
1354 TEST_1(!check_msg(tt, tt->tt_rmsg, "tls-last"));
1355 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1356
1357 tport_decref(&tp0);
1358
1359 /* Wait until notifications -
1360 client closes when idle and notifys pending,
1361 then server closes and notifys pending */
1362 while (pending_server_close || pending_client_close)
1363 su_root_step(tt->tt_root, 50);
1364
1365 #endif
1366
1367 END();
1368 }
1369
sigcomp_test(tp_test_t * tt)1370 static int sigcomp_test(tp_test_t *tt)
1371 {
1372 BEGIN();
1373
1374 #if HAVE_SIGCOMP
1375 su_home_t *home;
1376 tp_name_t tpn[1] = {{ NULL }};
1377 struct sigcomp_compartment *cc;
1378
1379 if (tt->tt_udp_comp->tpn_comp) {
1380 msg_t *msg = NULL;
1381
1382 TEST_1(cc = test_sigcomp_compartment(tt, tt->tt_tports, tt->tt_udp_comp));
1383
1384 TEST_1(!new_test_msg(tt, &msg, "udp-sigcomp", 1, 1200));
1385 test_create_md5(tt, msg);
1386 TEST_1(tport_tsend(tt->tt_tports,
1387 msg,
1388 tt->tt_udp_comp,
1389 TPTAG_COMPARTMENT(cc),
1390 TAG_END()));
1391 msg_destroy(msg);
1392
1393 TEST(tport_test_run(tt, 5), 1);
1394
1395 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
1396
1397 test_check_md5(tt, tt->tt_rmsg);
1398
1399 TEST_1(msg = tt->tt_rmsg); tt->tt_rmsg = NULL;
1400
1401 TEST_1(home = msg_home(msg));
1402
1403 TEST_1(tport_convert_addr(home, tpn, "udp", NULL, msg_addr(msg)) == 0);
1404
1405 tpn->tpn_comp = tport_name(tt->tt_rtport)->tpn_comp;
1406
1407 /* reply */
1408 TEST_1(cc = test_sigcomp_compartment(tt, tt->tt_tports, tpn));
1409 TEST_1(tport_tsend(tt->tt_rtport, msg, tpn,
1410 TPTAG_COMPARTMENT(cc),
1411 TAG_END()) != NULL);
1412
1413 msg_destroy(msg);
1414
1415 TEST(tport_test_run(tt, 5), 1);
1416
1417 TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
1418 test_check_md5(tt, tt->tt_rmsg);
1419 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1420 }
1421
1422 if (tt->tt_tcp_comp->tpn_comp) {
1423 tport_t *tp;
1424 msg_t *msg = NULL;
1425
1426 *tpn = *tt->tt_tcp_comp;
1427
1428 TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp", 1, 1500));
1429 test_create_md5(tt, msg);
1430
1431 tport_log->log_level = 9;
1432
1433 TEST_1(cc = test_sigcomp_compartment(tt, tt->tt_tports, tpn));
1434 TEST_1(tp = tport_tsend(tt->tt_tports,
1435 msg,
1436 tpn,
1437 TPTAG_COMPARTMENT(cc),
1438 TAG_END()));
1439 TEST_1(tport_incref(tp)); tport_decref(&tp);
1440 msg_destroy(msg);
1441
1442 TEST(tport_test_run(tt, 5), 1);
1443
1444 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp"));
1445 test_check_md5(tt, tt->tt_rmsg);
1446 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1447
1448 TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-2", 1, 3000));
1449 test_create_md5(tt, msg);
1450 TEST_1(tp = tport_tsend(tt->tt_tports,
1451 msg,
1452 tt->tt_tcp_comp,
1453 TPTAG_COMPARTMENT(cc),
1454 TAG_END()));
1455 TEST_1(tport_incref(tp)); tport_decref(&tp);
1456 msg_destroy(msg);
1457
1458 TEST(tport_test_run(tt, 5), 1);
1459
1460 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-2"));
1461 test_check_md5(tt, tt->tt_rmsg);
1462
1463 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1464
1465 TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-3", 1, 45500));
1466 test_create_md5(tt, msg);
1467 TEST_1(tp = tport_tsend(tt->tt_tports,
1468 msg,
1469 tt->tt_tcp_comp,
1470 TPTAG_COMPARTMENT(cc),
1471 TAG_END()));
1472 TEST_1(tport_incref(tp));
1473 msg_destroy(msg);
1474
1475 TEST(tport_test_run(tt, 5), 1);
1476
1477 tport_decref(&tp);
1478 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-3"));
1479 test_check_md5(tt, tt->tt_rmsg);
1480 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1481
1482 {
1483 tp_name_t tpn[1];
1484 tport_t *ctp, *rtp;
1485
1486 *tpn = *tt->tt_tcp_comp; tpn->tpn_comp = NULL;
1487
1488 TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-4", 1, 1000));
1489 test_create_md5(tt, msg);
1490 TEST_1(tp = tport_tsend(tt->tt_tports,
1491 msg,
1492 tpn,
1493 TPTAG_COMPARTMENT(cc),
1494 TPTAG_FRESH(1),
1495 TAG_END()));
1496 TEST_1(ctp = tport_incref(tp));
1497 msg_destroy(msg);
1498
1499 TEST(tport_test_run(tt, 5), 1);
1500
1501 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-4"));
1502 test_check_md5(tt, tt->tt_rmsg);
1503 TEST_1((msg_addrinfo(tt->tt_rmsg)->ai_flags & TP_AI_COMPRESSED) == 0);
1504 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1505 TEST_1(rtp = tport_incref(tt->tt_rtport));
1506
1507 TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-5", 1, 1000));
1508 test_create_md5(tt, msg);
1509 {
1510 /* Mess with internal data structures in order to
1511 force tport to use SigComp on this connection */
1512 tp_name_t *tpn = (tp_name_t *)tport_name(rtp);
1513 tpn->tpn_comp = "sigcomp";
1514 }
1515 TEST_1(tp = tport_tsend(rtp,
1516 msg,
1517 tt->tt_tcp_comp,
1518 TPTAG_COMPARTMENT(cc),
1519 TAG_END()));
1520 TEST_1(tport_incref(tp));
1521 msg_destroy(msg);
1522
1523 TEST(tp, rtp);
1524
1525 TEST(tport_test_run(tt, 5), 1);
1526
1527 tport_decref(&tp);
1528 TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-5"));
1529 test_check_md5(tt, tt->tt_rmsg);
1530 TEST_1((msg_addrinfo(tt->tt_rmsg)->ai_flags & TP_AI_COMPRESSED) != 0);
1531 msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
1532 TEST(ctp, tt->tt_rtport);
1533 tport_decref(&ctp);
1534 }
1535 }
1536 #endif
1537
1538 END();
1539 }
1540
1541 #if HAVE_SOFIA_STUN
1542
1543 #include <sofia-sip/stun_tag.h>
1544
stun_test(tp_test_t * tt)1545 static int stun_test(tp_test_t *tt)
1546 {
1547 BEGIN();
1548
1549 tport_t *mr;
1550 tp_name_t tpn[1] = {{ "*", "*", "*", "*", NULL }};
1551 #if HAVE_NETINET_SCTP_H
1552 char const * transports[] = { "udp", "tcp", "sctp", NULL };
1553 #else
1554 char const * transports[] = { "udp", "tcp", NULL };
1555 #endif
1556
1557 TEST_1(mr = tport_tcreate(tt, tp_test_class, tt->tt_root, TAG_END()));
1558
1559 TEST(tport_tbind(tt->tt_tports, tpn, transports, TPTAG_SERVER(1),
1560 STUNTAG_SERVER("999.999.999.999"),
1561 TAG_END()), -1);
1562
1563 tport_destroy(mr);
1564
1565 END();
1566 }
1567 #else
stun_test(tp_test_t * tt)1568 static int stun_test(tp_test_t *tt)
1569 {
1570 return 0;
1571 }
1572 #endif
1573
deinit_test(tp_test_t * tt)1574 static int deinit_test(tp_test_t *tt)
1575 {
1576 BEGIN();
1577
1578 /* Destroy client transports */
1579 tport_destroy(tt->tt_tports), tt->tt_tports = NULL;
1580
1581 /* Destroy server transports */
1582 tport_destroy(tt->tt_srv_tports), tt->tt_srv_tports = NULL;
1583
1584 #if HAVE_SIGCOMP
1585 sigcomp_state_handler_free(tt->state_handler); tt->state_handler = NULL;
1586 #endif
1587
1588 END();
1589 }
1590
1591 /* Test tport_tags filter */
filter_test(tp_test_t * tt)1592 static int filter_test(tp_test_t *tt)
1593 {
1594 tagi_t *lst, *result;
1595
1596 su_home_t home[1] = { SU_HOME_INIT(home) };
1597
1598 BEGIN();
1599
1600 lst = tl_list(TSTTAG_HEADER_STR("X: Y"),
1601 TAG_SKIP(2),
1602 TPTAG_IDENT("foo"),
1603 TSTTAG_HEADER_STR("X: Y"),
1604 TPTAG_IDENT("bar"),
1605 TAG_NULL());
1606
1607 TEST_1(lst);
1608
1609 result = tl_afilter(home, tport_tags, lst);
1610
1611 TEST_1(result);
1612 TEST_P(result[0].t_tag, tptag_ident);
1613 TEST_P(result[1].t_tag, tptag_ident);
1614
1615 free(lst);
1616 su_home_deinit(home);
1617
1618 END();
1619 }
1620
1621 #if HAVE_ALARM
1622 #include <signal.h>
1623
sig_alarm(int s)1624 static RETSIGTYPE sig_alarm(int s)
1625 {
1626 fprintf(stderr, "%s: FAIL! test timeout!\n", name);
1627 exit(1);
1628 }
1629
1630 char const alarm_option[] = " [--no-alarm]";
1631
1632 #else
1633 char const alarm_option[] = "";
1634 #endif
1635
usage(int exitcode)1636 void usage(int exitcode)
1637 {
1638 fprintf(stderr, "usage: %s [-v] [-a]%s\n", name, alarm_option);
1639 exit(exitcode);
1640 }
1641
main(int argc,char * argv[])1642 int main(int argc, char *argv[])
1643 {
1644 int flags = 0; /* XXX */
1645 int retval = 0;
1646 int no_alarm = 0;
1647 int i;
1648
1649 tp_test_t tt[1] = {{{ SU_HOME_INIT(tt) }}};
1650
1651 for (i = 1; argv[i]; i++) {
1652 if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbatim") == 0)
1653 tstflags |= tst_verbatim;
1654 else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--abort") == 0)
1655 tstflags |= tst_abort;
1656 else if (strcmp(argv[i], "--no-alarm") == 0)
1657 no_alarm = 1;
1658 else
1659 usage(1);
1660 }
1661
1662 #if HAVE_OPEN_C
1663 tstflags |= tst_verbatim;
1664 #endif
1665
1666 #if HAVE_ALARM
1667 if (!no_alarm) {
1668 signal(SIGALRM, sig_alarm);
1669 alarm(120);
1670 }
1671 #endif
1672
1673 /* Use log */
1674 if (flags & tst_verbatim)
1675 tport_log->log_default = 9;
1676 else
1677 tport_log->log_default = 1;
1678
1679 su_init();
1680
1681 retval |= name_test(tt); fflush(stdout);
1682 retval |= filter_test(tt); fflush(stdout);
1683
1684 retval |= init_test(tt); fflush(stdout);
1685 if (retval == 0) {
1686 retval |= sigcomp_test(tt); fflush(stdout);
1687 retval |= sctp_test(tt); fflush(stdout);
1688 retval |= udp_test(tt); fflush(stdout);
1689 retval |= tcp_test(tt); fflush(stdout);
1690 retval |= test_incomplete(tt); fflush(stdout);
1691 retval |= reuse_test(tt); fflush(stdout);
1692 retval |= tls_test(tt); fflush(stdout);
1693 if (0) /* Not yet working... */
1694 retval |= stun_test(tt); fflush(stdout);
1695 retval |= deinit_test(tt); fflush(stdout);
1696 }
1697
1698 su_deinit();
1699
1700 #if HAVE_OPEN_C
1701 sleep(10);
1702 #endif
1703
1704 return retval;
1705 }
1706
1707