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