12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706 |
- /*
- * This file is part of the Sofia-SIP package
- *
- * Copyright (C) 2006 Nokia Corporation.
- *
- * Contact: Pekka Pessi <pekka.pessi@nokia.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
- /**@CFILE tport_test.c
- *
- * Test functions for transports
- *
- * @internal
- *
- * @author Pekka Pessi <Pekka.Pessi@nokia.com>
- *
- * @date Created: Wed Apr 3 11:25:13 2002 ppessi
- */
- /* always assert()s */
- #undef NDEBUG
- #include "config.h"
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #include <stdio.h>
- #include <assert.h>
- typedef struct tp_test_s tp_test_t;
- #define TP_STACK_T tp_test_t
- #define TP_CLIENT_T struct called
- #include <sofia-sip/su_wait.h>
- #include <sofia-sip/su_md5.h>
- #include "tport_internal.h" /* Get SU_DEBUG_*() */
- #include "test_class.h"
- #include "test_protos.h"
- #include "sofia-sip/msg.h"
- #include "sofia-sip/msg_mclass.h"
- #include "sofia-sip/msg_addr.h"
- #if HAVE_SIGCOMP
- #include <sigcomp.h>
- #endif
- #include <sofia-sip/base64.h>
- #include <sofia-sip/su_log.h>
- #include "sofia-sip/tport.h"
- struct tp_test_s {
- su_home_t tt_home[1];
- int tt_flags;
- su_root_t *tt_root;
- msg_mclass_t *tt_mclass;
- tport_t *tt_srv_tports;
- tport_t *tt_tports;
- tport_t *tt_rtport;
- tp_name_t tt_udp_name[1];
- tp_name_t tt_udp_comp[1];
- tp_name_t tt_tcp_name[1];
- tp_name_t tt_tcp_comp[1];
- tp_name_t tt_sctp_name[1];
- tp_name_t tt_sctp_comp[1];
- tp_name_t tt_tls_name[1];
- tp_name_t tt_tls_comp[1];
- #if HAVE_SIGCOMP
- struct sigcomp_state_handler *state_handler;
- struct sigcomp_algorithm const *algorithm;
- struct sigcomp_compartment *master_cc;
- #define IF_SIGCOMP_TPTAG_COMPARTMENT(cc) TAG_IF(cc, TPTAG_COMPARTMENT(cc)),
- #else
- #define IF_SIGCOMP_TPTAG_COMPARTMENT(cc)
- #endif
- int tt_status;
- int tt_received;
- msg_t *tt_rmsg;
- uint8_t tt_digest[SU_MD5_DIGEST_SIZE];
- su_addrinfo_t const *tt_tcp_addr;
- tport_t *tt_tcp;
- };
- int tstflags;
- #define TSTFLAGS tstflags
- #include <sofia-sip/tstdef.h>
- char const name[] = "tport_test";
- SOFIAPUBVAR su_log_t tport_log[];
- static int name_test(tp_test_t *tt)
- {
- tp_name_t tpn[1];
- su_home_t home[1] = { SU_HOME_INIT(home) };
- su_sockaddr_t su[1];
- BEGIN();
- memset(su, 0, sizeof su);
- su->su_port = htons(5060);
- su->su_family = AF_INET;
- TEST(tport_convert_addr(home, tpn, "tcp", "localhost", su), 0);
- su->su_family = AF_INET;
- TEST(tport_convert_addr(home, tpn, "tcp", "localhost", su), 0);
- #if SU_HAVE_IN6
- su->su_family = AF_INET6;
- TEST(tport_convert_addr(home, tpn, "tcp", "localhost", su), 0);
- #endif
- END();
- }
- /* Count number of transports in chain */
- static
- int count_tports(tport_t *tp)
- {
- int n = 0;
- for (tp = tport_primaries(tp); tp; tp = tport_next(tp))
- n++;
- return n;
- }
- static int check_msg(tp_test_t *tt, msg_t *msg, char const *ident)
- {
- msg_test_t *tst;
- msg_payload_t *pl;
- usize_t i, len;
- BEGIN();
- TEST_1(tst = msg_test_public(msg));
- TEST_1(pl = tst->msg_payload);
- if (ident) {
- if (!tst->msg_content_location ||
- strcmp(ident, tst->msg_content_location->g_string))
- return 1;
- }
- len = pl->pl_len;
- for (i = 0; i < len; i++) {
- if (pl->pl_data[i] != (char) (i % 240))
- break;
- }
- if (pl)
- return i != len;
- END();
- }
- static int test_create_md5(tp_test_t *tt, msg_t *msg)
- {
- msg_test_t *tst;
- msg_payload_t *pl;
- su_md5_t md5[1];
- BEGIN();
- TEST_1(tst = msg_test_public(msg));
- TEST_1(pl = tst->msg_payload);
- su_md5_init(md5);
- su_md5_update(md5, pl->pl_data, pl->pl_len);
- su_md5_digest(md5, tt->tt_digest);
- END();
- }
- static int test_check_md5(tp_test_t *tt, msg_t *msg)
- {
- msg_test_t *tst;
- msg_payload_t *pl;
- su_md5_t md5[1];
- uint8_t digest[SU_MD5_DIGEST_SIZE];
- BEGIN();
- TEST_1(tst = msg_test_public(msg));
- TEST_1(pl = tst->msg_payload);
- su_md5_init(md5);
- su_md5_update(md5, pl->pl_data, pl->pl_len);
- su_md5_digest(md5, digest);
- TEST(memcmp(digest, tt->tt_digest, sizeof digest), 0);
- END();
- }
- static int test_msg_md5(tp_test_t *tt, msg_t *msg)
- {
- msg_test_t *tst;
- BEGIN();
- TEST_1(tst = msg_test_public(msg));
- if (tst->msg_content_md5) {
- su_md5_t md5sum[1];
- uint8_t digest[SU_MD5_DIGEST_SIZE];
- char b64[BASE64_SIZE(SU_MD5_DIGEST_SIZE) + 1];
- msg_payload_t *pl =tst->msg_payload;
- su_md5_init(md5sum);
- su_md5_update(md5sum, pl->pl_data, pl->pl_len);
- su_md5_digest(md5sum, digest);
- base64_e(b64, sizeof(b64), digest, sizeof(digest));
- if (strcmp(b64, tst->msg_content_md5->g_string)) {
- ;
- }
- TEST_S(b64, tst->msg_content_md5->g_string);
- } else {
- TEST_1(tst->msg_content_md5);
- }
- END();
- }
- #define TPORT_TEST_VERSION MSG_TEST_VERSION_CURRENT
- static int new_test_msg(tp_test_t *tt, msg_t **retval,
- char const *ident,
- int N, int len)
- {
- msg_t *msg;
- msg_test_t *tst;
- su_home_t *home;
- msg_request_t *rq;
- msg_unknown_t *u;
- msg_content_location_t *cl;
- msg_content_md5_t *md5;
- msg_content_length_t *l;
- msg_separator_t *sep;
- msg_payload_t payload[1];
- msg_header_t *h;
- int i;
- su_md5_t md5sum[1];
- uint8_t digest[SU_MD5_DIGEST_SIZE];
- char b64[BASE64_SIZE(SU_MD5_DIGEST_SIZE) + 1];
- BEGIN();
- TEST_1(msg = msg_create(tt->tt_mclass, 0));
- TEST_1(tst = msg_test_public(msg));
- TEST_1(home = msg_home(msg));
- TEST_SIZE(msg_maxsize(msg, 1024 + N * len), 0);
- TEST_1(rq = msg_request_make(home, "DO im:foo@faa " TPORT_TEST_VERSION));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)rq), 0);
- TEST_1(u = msg_unknown_make(home, "Foo: faa"));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)u), 0);
- TEST_1(u = msg_unknown_make(home, "Foo: faa"));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)u), 0);
- if (ident) {
- TEST_1(cl = msg_content_location_make(home, ident));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)cl), 0);
- }
- msg_payload_init(payload);
- payload->pl_len = len;
- TEST_1(payload->pl_data = su_zalloc(home, payload->pl_len));
- for (i = 0; i < len; i++) {
- payload->pl_data[i] = (char) (i % 240);
- }
- su_md5_init(md5sum);
- for (i = 0; i < N; i++) {
- h = msg_header_dup(home, (msg_header_t*)payload);
- TEST_1(h);
- TEST(msg_header_insert(msg, (void *)tst, h), 0);
- su_md5_update(md5sum, payload->pl_data, payload->pl_len);
- }
- TEST_1(l = msg_content_length_format(home, MOD_ZU, (size_t)(N * payload->pl_len)));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)l), 0);
- su_md5_digest(md5sum, digest);
- base64_e(b64, sizeof(b64), digest, sizeof(digest));
- TEST_1(md5 = msg_content_md5_make(home, b64));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)md5), 0);
- TEST_1(sep = msg_separator_create(home));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)sep), 0);
- TEST(msg_serialize(msg, (void *)tst), 0);
- *retval = msg;
- END();
- }
- static
- struct sigcomp_compartment *
- test_sigcomp_compartment(tp_test_t *tt, tport_t *tp, tp_name_t const *tpn);
- static void tp_test_recv(tp_test_t *tt,
- tport_t *tp,
- msg_t *msg,
- tp_magic_t *magic,
- su_time_t now)
- {
- tp_name_t frm[1];
- if (tport_delivered_from(tp, msg, frm) != -1 && frm->tpn_comp) {
- struct sigcomp_compartment *cc = test_sigcomp_compartment(tt, tp, frm);
- tport_sigcomp_accept(tp, cc, msg);
- }
- tt->tt_status = 1;
- tt->tt_received++;
- if (msg_has_error(msg)) {
- tt->tt_status = -1;
- tt->tt_rtport = tp;
- }
- else if (test_msg_md5(tt, msg))
- msg_destroy(msg);
- else if (tt->tt_rmsg)
- msg_destroy(msg);
- else {
- tt->tt_rmsg = msg;
- tt->tt_rtport = tp;
- }
- }
- static void tp_test_error(tp_test_t *tt,
- tport_t *tp,
- int errcode,
- char const *remote)
- {
- tt->tt_status = -1;
- fprintf(stderr, "tp_test_error(%p): error %d (%s) from %s\n",
- (void *)tp, errcode, su_strerror(errcode),
- remote ? remote : "<unknown destination>");
- }
- msg_t *tp_test_msg(tp_test_t *tt, int flags,
- char const data[], usize_t size,
- tport_t const *tp,
- tp_client_t *tpc)
- {
- msg_t *msg = msg_create(tt->tt_mclass, flags);
- msg_maxsize(msg, 2 * 1024 * 1024);
- return msg;
- }
- static
- struct sigcomp_compartment *
- test_sigcomp_compartment(tp_test_t *tt,
- tport_t *tp,
- tp_name_t const *tpn)
- {
- struct sigcomp_compartment *cc = NULL;
- #if HAVE_SIGCOMP
- char name[256];
- int namesize;
- namesize = snprintf(name, sizeof name, "TEST_%s/%s:%s",
- tpn->tpn_proto,
- tpn->tpn_host,
- tpn->tpn_port);
- if (namesize <= 0 || namesize >= sizeof name)
- return NULL;
- cc = sigcomp_compartment_access(tt->state_handler,
- 0, name, namesize, NULL, 0);
- if (cc == NULL) {
- cc = sigcomp_compartment_create(tt->algorithm, tt->state_handler,
- 0, name, namesize, NULL, 0);
- sigcomp_compartment_option(cc, "dms=32768");
- }
- #endif
- return cc;
- }
- /* Accept/reject early SigComp message */
- int test_sigcomp_accept(tp_stack_t *tt, tport_t *tp, msg_t *msg)
- {
- struct sigcomp_compartment *cc = NULL;
- cc = test_sigcomp_compartment(tt, tp, tport_name(tp));
- if (cc)
- tport_sigcomp_assign(tp, cc);
- return tport_sigcomp_accept(tp, cc, msg);
- }
- tp_stack_class_t const tp_test_class[1] =
- {{
- /* tpac_size */ sizeof(tp_test_class),
- /* tpac_recv */ tp_test_recv,
- /* tpac_error */ tp_test_error,
- /* tpac_alloc */ tp_test_msg,
- }};
- static int init_test(tp_test_t *tt)
- {
- tp_name_t myname[1] = {{ "*", "*", "*", "*", "sigcomp" }};
- #if HAVE_SCTP
- char const * transports[] = { "udp", "tcp", "sctp", NULL };
- #else
- char const * transports[] = { "udp", "tcp", NULL };
- #endif
- tp_name_t const *tpn;
- tport_t *tp;
- unsigned idle;
- int logging = -1;
- BEGIN();
- int mask = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST;
- #ifdef AI_ALL
- mask |= AI_ALL;
- #endif
- #ifdef AI_V4MAPPED_CFG
- mask |= AI_V4MAPPED_CFG;
- #endif
- #ifdef AI_ADDRCONFIG
- mask |= AI_ADDRCONFIG;
- #endif
- #ifdef AI_V4MAPPED
- mask |= AI_V4MAPPED;
- #endif
- /* Test that we have no common flags with underlying getaddrinfo() */
- TEST(mask & TP_AI_MASK, 0);
- TEST_1(tt->tt_root = su_root_create(NULL));
- myname->tpn_host = "127.0.0.1";
- myname->tpn_ident = "client";
- /* Create message class */
- TEST_1(tt->tt_mclass = msg_mclass_clone(msg_test_mclass, 0, 0));
- /* Try to insert Content-Length header (expecting failure) */
- TEST(msg_mclass_insert(tt->tt_mclass, msg_content_length_href), -1);
- #if HAVE_SIGCOMP
- TEST_1(tt->state_handler = sigcomp_state_handler_create());
- TEST_1(tt->algorithm =
- sigcomp_algorithm_by_name(getenv("SIGCOMP_ALGORITHM")));
- TEST_1(tt->master_cc =
- sigcomp_compartment_create(tt->algorithm, tt->state_handler,
- 0, "", 0, NULL, 0));
- TEST(sigcomp_compartment_option(tt->master_cc, "stateless"), 1);
- #endif
- /* Create client transport */
- TEST_1(tt->tt_tports =
- tport_tcreate(tt, tp_test_class, tt->tt_root,
- IF_SIGCOMP_TPTAG_COMPARTMENT(tt->master_cc)
- TAG_END()));
- /* Bind client transports */
- TEST(tport_tbind(tt->tt_tports, myname, transports,
- TPTAG_SERVER(0), TAG_END()),
- 0);
- if (getenv("TPORT_TEST_HOST"))
- myname->tpn_host = getenv("TPORT_TEST_HOST");
- else
- myname->tpn_host = "*";
- if (getenv("TPORT_TEST_PORT"))
- myname->tpn_port = getenv("TPORT_TEST_PORT");
- myname->tpn_ident = "server";
- /* Create server transport */
- TEST_1(tt->tt_srv_tports =
- tport_tcreate(tt, tp_test_class, tt->tt_root,
- IF_SIGCOMP_TPTAG_COMPARTMENT(tt->master_cc)
- TAG_END()));
- /* Bind server transports */
- TEST(tport_tbind(tt->tt_srv_tports, myname, transports,
- TPTAG_SERVER(1),
- TAG_END()),
- 0);
- /* Check that the master transport has idle parameter */
- TEST(tport_get_params(tt->tt_srv_tports,
- TPTAG_IDLE_REF(idle),
- TAG_END()), 1);
- /* Check that logging tag works */
- TEST(tport_get_params(tt->tt_srv_tports,
- TPTAG_LOG_REF(logging),
- TAG_END()), 1);
- TEST(tport_set_params(tt->tt_srv_tports,
- TPTAG_LOG(logging),
- TAG_END()), 1);
- for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp))
- TEST_S(tport_name(tp)->tpn_ident, "server");
- {
- su_sockaddr_t su[1];
- socklen_t sulen;
- int s;
- int i, before, after;
- char port[8];
- tp_name_t rname[1];
- *rname = *myname;
- /* Check that we cannot bind to an already used socket */
- memset(su, 0, sulen = sizeof(su->su_sin));
- s = su_socket(su->su_family = AF_INET, SOCK_STREAM, 0); TEST_1(s != -1);
- TEST_1(bind(s, &su->su_sa, sulen) != -1);
- TEST_1(listen(s, 5) != -1);
- TEST_1(getsockname(s, &su->su_sa, &sulen) != -1);
- sprintf(port, "%u", ntohs(su->su_port));
- rname->tpn_port = port;
- rname->tpn_ident = "failure";
- before = count_tports(tt->tt_srv_tports);
- /* Bind server transports to an reserved port - this should fail */
- TEST(tport_tbind(tt->tt_srv_tports, rname, transports,
- TPTAG_SERVER(1),
- TAG_END()),
- -1);
- after = count_tports(tt->tt_srv_tports);
- /* Check that no new primary transports has been added by failed call */
- TEST(before, after);
- /* Add new transports to an ephemeral port with new identity */
- for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp))
- TEST_S(tport_name(tp)->tpn_ident, "server");
- rname->tpn_port = "*";
- rname->tpn_ident = "server2";
- /* Bind server transports to another port */
- TEST(tport_tbind(tt->tt_srv_tports, rname, transports,
- TPTAG_SERVER(1),
- TAG_END()),
- 0);
- /* Check that new transports are after old ones. */
- for (i = 0, tp = tport_primaries(tt->tt_srv_tports);
- i < before;
- i++, tp = tport_next(tp))
- TEST_S(tport_name(tp)->tpn_ident, "server");
- for (; tp; tp = tport_next(tp))
- TEST_S(tport_name(tp)->tpn_ident, "server2");
- }
- #if HAVE_TLS
- {
- tp_name_t tlsname[1] = {{ "tls", "*", "*", "*", NULL }};
- char const * transports[] = { "tls", NULL };
- char const *srcdir = getenv("srcdir");
- if (srcdir == NULL)
- srcdir = ".";
- tlsname->tpn_host = myname->tpn_host;
- tlsname->tpn_ident = "server";
- /* Bind client transports */
- TEST(tport_tbind(tt->tt_tports, tlsname, transports,
- TPTAG_SERVER(0),
- TPTAG_CERTIFICATE(srcdir),
- TAG_END()),
- 0);
- /* Bind tls server transport */
- TEST(tport_tbind(tt->tt_srv_tports, tlsname, transports,
- TPTAG_SERVER(1),
- TPTAG_CERTIFICATE(srcdir),
- TAG_END()),
- 0);
- }
- #endif
- for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp)) {
- TEST_1(tpn = tport_name(tp));
- if (tt->tt_flags & tst_verbatim) {
- char const *host = tpn->tpn_host != tpn->tpn_canon ? tpn->tpn_host : "";
- printf("bound transport to %s/%s:%s%s%s%s%s\n",
- tpn->tpn_proto, tpn->tpn_canon, tpn->tpn_port,
- host[0] ? ";maddr=" : "", host,
- tpn->tpn_comp ? ";comp=" : "",
- tpn->tpn_comp ? tpn->tpn_comp : "");
- }
- /* Ignore server2 tports for now */
- if (strcmp(tpn->tpn_ident, "server"))
- continue;
- if (strcmp(tpn->tpn_proto, "udp") == 0) {
- *tt->tt_udp_name = *tpn;
- tt->tt_udp_name->tpn_comp = NULL;
- tt->tt_udp_name->tpn_ident = NULL;
- *tt->tt_udp_comp = *tpn;
- tt->tt_udp_comp->tpn_ident = NULL;
- }
- else if (strcmp(tpn->tpn_proto, "tcp") == 0) {
- *tt->tt_tcp_name = *tpn;
- tt->tt_tcp_name->tpn_comp = NULL;
- tt->tt_tcp_name->tpn_ident = NULL;
- *tt->tt_tcp_comp = *tpn;
- tt->tt_tcp_comp->tpn_ident = NULL;
- if (tt->tt_tcp_addr == NULL) {
- tt->tt_tcp_addr = tport_get_address(tp);
- tt->tt_tcp = tp;
- }
- }
- else if (strcmp(tpn->tpn_proto, "sctp") == 0) {
- *tt->tt_sctp_name = *tpn;
- tt->tt_sctp_name->tpn_ident = NULL;
- }
- else if (strcmp(tpn->tpn_proto, "tls") == 0) {
- *tt->tt_tls_name = *tpn;
- tt->tt_tls_name->tpn_ident = NULL;
- }
- }
- END();
- }
- char const payload[] =
- "Some data\n"
- "More data\n";
- #include <time.h>
- int
- tport_test_run(tp_test_t *tt, unsigned timeout)
- {
- time_t now = time(NULL);
- tt->tt_status = 0;
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- tt->tt_rtport = NULL;
- while (!tt->tt_status) {
- if (tt->tt_flags & tst_verbatim) {
- fputs(".", stdout); fflush(stdout);
- }
- su_root_step(tt->tt_root, 500L);
- if (!getenv("TPORT_TEST_DEBUG") &&
- time(NULL) > (time_t)(now + timeout))
- return 0;
- }
- return tt->tt_status;
- }
- static int udp_test(tp_test_t *tt)
- {
- tport_t *tp;
- msg_t *msg;
- msg_test_t *tst;
- su_home_t *home;
- msg_request_t *rq;
- msg_unknown_t *u;
- msg_content_length_t *l;
- msg_content_md5_t *md5;
- msg_separator_t *sep;
- msg_payload_t *pl;
- BEGIN();
- TEST_1(msg = msg_create(tt->tt_mclass, 0));
- TEST_1(tst = msg_test_public(msg));
- TEST_1(home = msg_home(msg));
- TEST_1(rq = msg_request_make(home, "DO im:foo@faa " TPORT_TEST_VERSION));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)rq), 0);
- TEST_1(u = msg_unknown_make(home, "Foo: faa"));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)u), 0);
- TEST_1(pl = msg_payload_make(home, payload));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)pl), 0);
- TEST_1(l = msg_content_length_format(home, MOD_ZU, (size_t)pl->pl_len));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)l), 0);
- TEST_1(md5 = msg_content_md5_make(home, "R6nitdrtJFpxYzrPaSXfrA=="));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)md5), 0);
- TEST_1(sep = msg_separator_create(home));
- TEST(msg_header_insert(msg, (void *)tst, (msg_header_t *)sep), 0);
- TEST(msg_serialize(msg, (void *)tst), 0);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_udp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST(tport_test_run(tt, 5), 1);
- msg_destroy(msg);
- #if 0
- tp_name_t tpn[1] = {{ NULL }};
- TEST_1(msg = tt->tt_rmsg); tt->tt_rmsg = NULL;
- TEST_1(home = msg_home(msg));
- TEST_1(tport_convert_addr(home, tpn, "udp", NULL, msg_addr(msg)) == 0);
- tpn->tpn_comp = tport_name(tt->tt_rtport)->tpn_comp;
- /* reply */
- TEST_1(tport_tsend(tt->tt_rtport, msg, tpn, TAG_END()) != NULL);
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- msg_destroy(msg);
- #endif
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- END();
- }
- int pending_server_close, pending_client_close;
- void server_closed_callback(tp_stack_t *tt, tp_client_t *client,
- tport_t *tp, msg_t *msg, int error)
- {
- assert(msg == NULL);
- assert(client == NULL);
- if (msg == NULL) {
- tport_release(tp, pending_server_close, NULL, NULL, client, 0);
- pending_server_close = 0;
- }
- }
- void client_closed_callback(tp_stack_t *tt, tp_client_t *client,
- tport_t *tp, msg_t *msg, int error)
- {
- assert(msg == NULL);
- assert(client == NULL);
- if (msg == NULL) {
- tport_release(tp, pending_client_close, NULL, NULL, client, 0);
- pending_client_close = 0;
- }
- }
- static int tcp_test(tp_test_t *tt)
- {
- BEGIN();
- msg_t *msg = NULL;
- int i, N;
- tport_t *tp, *tp0;
- char ident[16];
- su_time_t started;
- /* Send a single message */
- TEST_1(!new_test_msg(tt, &msg, "tcp-first", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- tp0 = tport_incref(tp);
- msg_destroy(msg);
- tport_set_params(tp,
- TPTAG_KEEPALIVE(100),
- TPTAG_PINGPONG(500),
- TPTAG_IDLE(500),
- TAG_END());
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-first"));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- /* Ask for notification upon close */
- pending_client_close = tport_pend(tp0, NULL, client_closed_callback, NULL);
- TEST_1(pending_client_close > 0);
- tp = tt->tt_rtport;
- pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
- TEST_1(pending_server_close > 0);
- N = 0; tt->tt_received = 0;
- #ifndef WIN32 /* Windows seems to be buffering too much */
- /* Create a large message, just to force queueing in sending end */
- TEST(new_test_msg(tt, &msg, "tcp-0", 1, 16 * 64 * 1024), 0);
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- N++;
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
- msg_destroy(msg);
- /* Fill up the queue */
- for (i = 1; i < TPORT_QUEUESIZE; i++) {
- snprintf(ident, sizeof ident, "tcp-%u", i);
- TEST(new_test_msg(tt, &msg, ident, 1, 64 * 1024), 0);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- N++;
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
- msg_destroy(msg);
- }
- /* This overflows the queue */
- TEST(new_test_msg(tt, &msg, "tcp-overflow", 1, 1024), 0);
- //TEST_1(!tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 60), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-0"));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- if (tt->tt_received < TPORT_QUEUESIZE) { /* We have not received it all */
- snprintf(ident, sizeof ident, "tcp-%u", tt->tt_received);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, ident));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- #else
- (void)i; (void)ident;
- #endif
- /* This uses a new connection */
- TEST_1(!new_test_msg(tt, &msg, "tcp-no-reuse", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
- TPTAG_REUSE(0), TAG_END()));
- N++;
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_1(tport_incref(tp) != tp0); tport_decref(&tp);
- msg_destroy(msg);
- /* This uses the old connection */
- TEST_1(!new_test_msg(tt, &msg, "tcp-reuse", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
- TPTAG_REUSE(1), TAG_END()));
- N++;
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_1(tport_incref(tp) == tp0); tport_decref(&tp);
- msg_destroy(msg);
- /* Receive every message from queue */
- while (tt->tt_received < N) {
- TEST(tport_test_run(tt, 5), 1);
- /* Validate message */
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- /* Try to send a single message */
- TEST_1(!new_test_msg(tt, &msg, "tcp-last", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-last"));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST_1(pending_server_close && pending_client_close);
- SU_DEBUG_3(("tport_test(%p): waiting for PONG timeout\n", (void *)tp0));
- /* Wait until notifications -
- client closes when no pong is received and notifys pending,
- then server closes and notifys pending */
- while (pending_server_close || pending_client_close)
- su_root_step(tt->tt_root, 50);
- tport_decref(&tp0);
- /* Again a single message */
- TEST_1(!new_test_msg(tt, &msg, "tcp-pingpong", 1, 512));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- tp0 = tport_incref(tp);
- msg_destroy(msg);
- tport_set_params(tp0,
- TPTAG_KEEPALIVE(250),
- TPTAG_PINGPONG(200),
- TAG_END());
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-pingpong"));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- /* Ask for notifications upon close */
- pending_client_close = tport_pend(tp0, NULL, client_closed_callback, NULL);
- TEST_1(pending_client_close > 0);
- tp = tt->tt_rtport;
- pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
- TEST_1(pending_server_close > 0);
- /* Now server responds with pong ... */
- TEST(tport_set_params(tp, TPTAG_PONG2PING(1), TAG_END()), 1);
- started = su_now();
- while (pending_server_close && pending_client_close) {
- su_root_step(tt->tt_root, 50);
- if (su_duration(su_now(), started) > 1000)
- break;
- }
- /* ... and we are still pending after a second */
- TEST_1(pending_client_close && pending_server_close);
- TEST_1(su_duration(su_now(), started) > 1000);
- tport_shutdown(tp0, 2);
- tport_unref(tp0);
- while (pending_server_close || pending_client_close)
- su_root_step(tt->tt_root, 50);
- END();
- }
- static int test_incomplete(tp_test_t *tt)
- {
- BEGIN();
- su_addrinfo_t const *ai = tt->tt_tcp_addr;
- su_socket_t s;
- int connected;
- TEST_1(ai != NULL);
- TEST(tport_set_params(tt->tt_tcp, TPTAG_TIMEOUT(500), TAG_END()), 1);
- s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- TEST_1(s != SOCKET_ERROR);
- su_setblocking(s, 1);
- connected = connect(s, ai->ai_addr, (socklen_t)ai->ai_addrlen);
- su_root_step(tt->tt_root, 50);
- TEST(su_send(s, "F", 1, 0), 1);
- su_root_step(tt->tt_root, 50);
- TEST(su_send(s, "O", 1, 0), 1);
- su_root_step(tt->tt_root, 50);
- TEST(su_send(s, "O", 1, 0), 1);
- su_root_step(tt->tt_root, 50);
- TEST(su_send(s, " ", 1, 0), 1);
- su_root_step(tt->tt_root, 50);
- tt->tt_received = 0;
- TEST(tport_test_run(tt, 5), -1);
- TEST(tt->tt_received, 1);
- TEST_P(tt->tt_rmsg, NULL);
- su_close(s);
- END();
- }
- static int reuse_test(tp_test_t *tt)
- {
- msg_t *msg = NULL;
- int i, reuse = -1;
- tport_t *tp, *tp0, *tp1;
- tp_name_t tpn[1];
- BEGIN();
- /* Flush existing connections */
- *tpn = *tt->tt_tcp_name;
- tpn->tpn_port = "*";
- TEST_1(tp = tport_by_name(tt->tt_tports, tpn));
- TEST_1(tport_is_primary(tp));
- TEST(tport_flush(tp), 0);
- for (i = 0; i < 10; i++)
- su_root_step(tt->tt_root, 10L);
- TEST(tport_set_params(tp, TPTAG_REUSE(0), TAG_END()), 1);
- /* Send two messages */
- TEST(new_test_msg(tt, &msg, "reuse-1", 1, 1024), 0);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_1(tp0 = tport_incref(tp));
- TEST(tport_get_params(tp, TPTAG_REUSE_REF(reuse), TAG_END()), 1);
- TEST(reuse, 0);
- msg_destroy(msg), msg = NULL;
- TEST(new_test_msg(tt, &msg, "reuse-2", 1, 1024), 0);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_1(tp1 = tport_incref(tp)); TEST_1(tp0 != tp1);
- TEST(tport_get_params(tp, TPTAG_REUSE_REF(reuse), TAG_END()), 1);
- TEST(reuse, 0);
- msg_destroy(msg), msg = NULL;
- /* Receive every message from queue */
- for (tt->tt_received = 0;
- tt->tt_received < 2;) {
- TEST(tport_test_run(tt, 5), 1);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- /* Enable reuse on single connection */
- TEST(tport_set_params(tp1, TPTAG_REUSE(1), TAG_END()), 1);
- TEST(new_test_msg(tt, &msg, "reuse-3", 1, 1024), 0);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
- TPTAG_REUSE(1),
- TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_1(tp1 == tp);
- TEST(tport_get_params(tp, TPTAG_REUSE_REF(reuse), TAG_END()), 1);
- TEST(reuse, 1);
- msg_destroy(msg), msg = NULL;
- TEST(tport_test_run(tt, 5), 1);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST_1(tp = tport_by_name(tt->tt_tports, tpn));
- TEST_1(tport_is_primary(tp));
- TEST(tport_set_params(tp, TPTAG_REUSE(1), TAG_END()), 1);
- /* Send a single message with different connection */
- TEST_1(!new_test_msg(tt, &msg, "fresh-1", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_tcp_name,
- TPTAG_FRESH(1),
- TPTAG_REUSE(1),
- TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- TEST_1(tport_incref(tp) != tp1); tport_decref(&tp);
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "fresh-1"));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST_1(tport_shutdown(tp0, 2) >= 0);
- TEST_1(tport_shutdown(tp1, 2) >= 0);
- TEST_1(tport_shutdown(tp0, 1) >= 0);
- TEST(tport_shutdown(NULL, 0), -1);
- tport_decref(&tp0);
- tport_decref(&tp1);
- END();
- }
- static int sctp_test(tp_test_t *tt)
- {
- BEGIN();
- msg_t *msg = NULL;
- int i, n;
- tport_t *tp, *tp0;
- char buffer[32];
- if (!tt->tt_sctp_name->tpn_proto)
- return 0;
- /* Just a small and nice message first */
- TEST_1(!new_test_msg(tt, &msg, "cid:sctp-first", 1, 1024));
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- msg_destroy(msg);
- tport_set_params(tp, TPTAG_KEEPALIVE(100), TPTAG_IDLE(500), TAG_END());
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- tp0 = tport_ref(tp);
- pending_server_close = pending_client_close = 0;
- /* Ask for notification upon close */
- pending_client_close = tport_pend(tp, NULL, client_closed_callback, NULL);
- TEST_1(pending_client_close > 0);
- tp = tt->tt_rtport;
- pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
- TEST_1(pending_server_close > 0);
- if (0) { /* SCTP does not work reliably. Really. */
- tt->tt_received = 0;
- /* Create large messages, just to force queueing in sending end */
- for (n = 0; !tport_queuelen(tp); n++) {
- snprintf(buffer, sizeof buffer, "cid:sctp-%u", n);
- TEST_1(!new_test_msg(tt, &msg, buffer, 1, 32000));
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tp0, msg, tt->tt_sctp_name, TAG_END()));
- TEST_S(tport_name(tp)->tpn_ident, "client");
- msg_destroy(msg);
- }
- /* Fill up the queue */
- for (i = 1; i < TPORT_QUEUESIZE; i++) {
- snprintf(buffer, sizeof buffer, "cid:sctp-%u", n + i);
- TEST_1(!new_test_msg(tt, &msg, buffer, 1, 1024));
- TEST_1(tp = tport_tsend(tp0, msg, tt->tt_sctp_name, TAG_END()));
- msg_destroy(msg);
- }
- /* Try to overflow the queue */
- snprintf(buffer, sizeof buffer, "cid:sctp-%u", n + i);
- TEST_1(!new_test_msg(tt, &msg, buffer, 1, 1024));
- TEST_1(!tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name, TAG_END()));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- /* This uses a new connection */
- TEST_1(!new_test_msg(tt, &msg, "cid:sctp-new", 1, 1024));
- TEST_1(tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name,
- TPTAG_REUSE(0), TAG_END()));
- msg_destroy(msg);
- /* Receive every message from queue */
- for (; tt->tt_received < n + TPORT_QUEUESIZE - 1;) {
- TEST(tport_test_run(tt, 10), 1);
- /* Validate message */
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- /* Try to send a single message */
- TEST_1(!new_test_msg(tt, &msg, "cid:sctp-final", 1, 512));
- TEST_1(tport_tsend(tt->tt_tports, msg, tt->tt_sctp_name, TAG_END()));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 10), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- tport_unref(tp0);
- /* Wait until notifications -
- client closes when idle and notifys pending,
- then server closes and notifys pending */
- while (pending_server_close || pending_client_close)
- su_root_step(tt->tt_root, 50);
- END();
- }
- struct called {
- int n, error, pending, released;
- };
- static
- void tls_error_callback(tp_stack_t *tt, tp_client_t *client,
- tport_t *tp, msg_t *msg, int error)
- {
- struct called *called = (struct called *)client;
- tt->tt_status = -1;
- called->n++, called->error = error;
- if (called->pending) {
- called->released = tport_release(tp, called->pending, msg, NULL, client, 0);
- called->pending = 0;
- }
- }
- static int tls_test(tp_test_t *tt)
- {
- BEGIN();
- #if HAVE_TLS
- tp_name_t const *dst = tt->tt_tls_name;
- msg_t *msg = NULL;
- int i;
- char ident[16];
- tport_t *tp, *tp0;
- struct called called[1] = {{ 0, 0, 0, 0 }};
- TEST_S(dst->tpn_proto, "tls");
- /* Send a single message */
- TEST_1(!new_test_msg(tt, &msg, "tls-first", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
- TEST_1(tp0 = tport_ref(tp));
- TEST_1(called->pending = tport_pend(tp, msg, tls_error_callback, (tp_client_t *)called));
- i = tport_test_run(tt, 5);
- msg_destroy(msg);
- if (i < 0) {
- if (called->n) {
- TEST(called->released, 0);
- puts("test_tport: skipping TLS tests");
- tport_unref(tp0);
- return 0;
- }
- }
- TEST(i, 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tls-first"));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- tport_set_params(tp, TPTAG_KEEPALIVE(100), TPTAG_IDLE(500), TAG_END());
- /* Ask for notification upon close */
- pending_client_close = tport_pend(tp0, NULL, client_closed_callback, NULL);
- TEST_1(pending_client_close > 0);
- tp = tt->tt_rtport;
- pending_server_close = tport_pend(tp, NULL, server_closed_callback, NULL);
- TEST_1(pending_server_close > 0);
- /* Send a largish message */
- TEST_1(!new_test_msg(tt, &msg, "tls-0", 16, 16 * 1024));
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
- TEST_1(tp == tp0);
- msg_destroy(msg);
- /* Fill up the queue */
- for (i = 1; i < TPORT_QUEUESIZE; i++) {
- snprintf(ident, sizeof ident, "tls-%u", i);
- TEST_1(!new_test_msg(tt, &msg, ident, 2, 512));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
- TEST_1(tp == tp0);
- msg_destroy(msg);
- }
- /* This uses a new connection */
- TEST_1(!new_test_msg(tt, &msg, "tls-no-reuse", 1, 1024));
- TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst,
- TPTAG_REUSE(0), TAG_END()));
- TEST_1(tp != tp0);
- msg_destroy(msg);
- tt->tt_received = 0;
- /* Receive every message from queue */
- while (tt->tt_received < TPORT_QUEUESIZE + 1) {
- TEST(tport_test_run(tt, 5), 1);
- /* Validate message */
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- /* Try to send a single message */
- TEST_1(!new_test_msg(tt, &msg, "tls-last", 1, 1024));
- TEST_1(tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tls-last"));
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- tport_decref(&tp0);
- /* Wait until notifications -
- client closes when idle and notifys pending,
- then server closes and notifys pending */
- while (pending_server_close || pending_client_close)
- su_root_step(tt->tt_root, 50);
- #endif
- END();
- }
- static int sigcomp_test(tp_test_t *tt)
- {
- BEGIN();
- #if HAVE_SIGCOMP
- su_home_t *home;
- tp_name_t tpn[1] = {{ NULL }};
- struct sigcomp_compartment *cc;
- if (tt->tt_udp_comp->tpn_comp) {
- msg_t *msg = NULL;
- TEST_1(cc = test_sigcomp_compartment(tt, tt->tt_tports, tt->tt_udp_comp));
- TEST_1(!new_test_msg(tt, &msg, "udp-sigcomp", 1, 1200));
- test_create_md5(tt, msg);
- TEST_1(tport_tsend(tt->tt_tports,
- msg,
- tt->tt_udp_comp,
- TPTAG_COMPARTMENT(cc),
- TAG_END()));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- test_check_md5(tt, tt->tt_rmsg);
- TEST_1(msg = tt->tt_rmsg); tt->tt_rmsg = NULL;
- TEST_1(home = msg_home(msg));
- TEST_1(tport_convert_addr(home, tpn, "udp", NULL, msg_addr(msg)) == 0);
- tpn->tpn_comp = tport_name(tt->tt_rtport)->tpn_comp;
- /* reply */
- TEST_1(cc = test_sigcomp_compartment(tt, tt->tt_tports, tpn));
- TEST_1(tport_tsend(tt->tt_rtport, msg, tpn,
- TPTAG_COMPARTMENT(cc),
- TAG_END()) != NULL);
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, NULL));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- }
- if (tt->tt_tcp_comp->tpn_comp) {
- tport_t *tp;
- msg_t *msg = NULL;
- *tpn = *tt->tt_tcp_comp;
- TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp", 1, 1500));
- test_create_md5(tt, msg);
- tport_log->log_level = 9;
- TEST_1(cc = test_sigcomp_compartment(tt, tt->tt_tports, tpn));
- TEST_1(tp = tport_tsend(tt->tt_tports,
- msg,
- tpn,
- TPTAG_COMPARTMENT(cc),
- TAG_END()));
- TEST_1(tport_incref(tp)); tport_decref(&tp);
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp"));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-2", 1, 3000));
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tt->tt_tports,
- msg,
- tt->tt_tcp_comp,
- TPTAG_COMPARTMENT(cc),
- TAG_END()));
- TEST_1(tport_incref(tp)); tport_decref(&tp);
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-2"));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-3", 1, 45500));
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tt->tt_tports,
- msg,
- tt->tt_tcp_comp,
- TPTAG_COMPARTMENT(cc),
- TAG_END()));
- TEST_1(tport_incref(tp));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- tport_decref(&tp);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-3"));
- test_check_md5(tt, tt->tt_rmsg);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- {
- tp_name_t tpn[1];
- tport_t *ctp, *rtp;
- *tpn = *tt->tt_tcp_comp; tpn->tpn_comp = NULL;
- TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-4", 1, 1000));
- test_create_md5(tt, msg);
- TEST_1(tp = tport_tsend(tt->tt_tports,
- msg,
- tpn,
- TPTAG_COMPARTMENT(cc),
- TPTAG_FRESH(1),
- TAG_END()));
- TEST_1(ctp = tport_incref(tp));
- msg_destroy(msg);
- TEST(tport_test_run(tt, 5), 1);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-4"));
- test_check_md5(tt, tt->tt_rmsg);
- TEST_1((msg_addrinfo(tt->tt_rmsg)->ai_flags & TP_AI_COMPRESSED) == 0);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST_1(rtp = tport_incref(tt->tt_rtport));
- TEST_1(!new_test_msg(tt, &msg, "tcp-sigcomp-5", 1, 1000));
- test_create_md5(tt, msg);
- {
- /* Mess with internal data structures in order to
- force tport to use SigComp on this connection */
- tp_name_t *tpn = (tp_name_t *)tport_name(rtp);
- tpn->tpn_comp = "sigcomp";
- }
- TEST_1(tp = tport_tsend(rtp,
- msg,
- tt->tt_tcp_comp,
- TPTAG_COMPARTMENT(cc),
- TAG_END()));
- TEST_1(tport_incref(tp));
- msg_destroy(msg);
- TEST(tp, rtp);
- TEST(tport_test_run(tt, 5), 1);
- tport_decref(&tp);
- TEST_1(!check_msg(tt, tt->tt_rmsg, "tcp-sigcomp-5"));
- test_check_md5(tt, tt->tt_rmsg);
- TEST_1((msg_addrinfo(tt->tt_rmsg)->ai_flags & TP_AI_COMPRESSED) != 0);
- msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
- TEST(ctp, tt->tt_rtport);
- tport_decref(&ctp);
- }
- }
- #endif
- END();
- }
- #if HAVE_SOFIA_STUN
- #include <sofia-sip/stun_tag.h>
- static int stun_test(tp_test_t *tt)
- {
- BEGIN();
- tport_t *mr;
- tp_name_t tpn[1] = {{ "*", "*", "*", "*", NULL }};
- #if HAVE_NETINET_SCTP_H
- char const * transports[] = { "udp", "tcp", "sctp", NULL };
- #else
- char const * transports[] = { "udp", "tcp", NULL };
- #endif
- TEST_1(mr = tport_tcreate(tt, tp_test_class, tt->tt_root, TAG_END()));
- TEST(tport_tbind(tt->tt_tports, tpn, transports, TPTAG_SERVER(1),
- STUNTAG_SERVER("999.999.999.999"),
- TAG_END()), -1);
- tport_destroy(mr);
- END();
- }
- #else
- static int stun_test(tp_test_t *tt)
- {
- return 0;
- }
- #endif
- static int deinit_test(tp_test_t *tt)
- {
- BEGIN();
- /* Destroy client transports */
- tport_destroy(tt->tt_tports), tt->tt_tports = NULL;
- /* Destroy server transports */
- tport_destroy(tt->tt_srv_tports), tt->tt_srv_tports = NULL;
- #if HAVE_SIGCOMP
- sigcomp_state_handler_free(tt->state_handler); tt->state_handler = NULL;
- #endif
- END();
- }
- /* Test tport_tags filter */
- static int filter_test(tp_test_t *tt)
- {
- tagi_t *lst, *result;
- su_home_t home[1] = { SU_HOME_INIT(home) };
- BEGIN();
- lst = tl_list(TSTTAG_HEADER_STR("X: Y"),
- TAG_SKIP(2),
- TPTAG_IDENT("foo"),
- TSTTAG_HEADER_STR("X: Y"),
- TPTAG_IDENT("bar"),
- TAG_NULL());
- TEST_1(lst);
- result = tl_afilter(home, tport_tags, lst);
- TEST_1(result);
- TEST_P(result[0].t_tag, tptag_ident);
- TEST_P(result[1].t_tag, tptag_ident);
- free(lst);
- su_home_deinit(home);
- END();
- }
- #if HAVE_ALARM
- #include <signal.h>
- static RETSIGTYPE sig_alarm(int s)
- {
- fprintf(stderr, "%s: FAIL! test timeout!\n", name);
- exit(1);
- }
- char const alarm_option[] = " [--no-alarm]";
- #else
- char const alarm_option[] = "";
- #endif
- void usage(int exitcode)
- {
- fprintf(stderr, "usage: %s [-v] [-a]%s\n", name, alarm_option);
- exit(exitcode);
- }
- int main(int argc, char *argv[])
- {
- int flags = 0; /* XXX */
- int retval = 0;
- int no_alarm = 0;
- int i;
- tp_test_t tt[1] = {{{ SU_HOME_INIT(tt) }}};
- for (i = 1; argv[i]; i++) {
- if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbatim") == 0)
- tstflags |= tst_verbatim;
- else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--abort") == 0)
- tstflags |= tst_abort;
- else if (strcmp(argv[i], "--no-alarm") == 0)
- no_alarm = 1;
- else
- usage(1);
- }
- #if HAVE_OPEN_C
- tstflags |= tst_verbatim;
- #endif
- #if HAVE_ALARM
- if (!no_alarm) {
- signal(SIGALRM, sig_alarm);
- alarm(120);
- }
- #endif
- /* Use log */
- if (flags & tst_verbatim)
- tport_log->log_default = 9;
- else
- tport_log->log_default = 1;
- su_init();
- retval |= name_test(tt); fflush(stdout);
- retval |= filter_test(tt); fflush(stdout);
- retval |= init_test(tt); fflush(stdout);
- if (retval == 0) {
- retval |= sigcomp_test(tt); fflush(stdout);
- retval |= sctp_test(tt); fflush(stdout);
- retval |= udp_test(tt); fflush(stdout);
- retval |= tcp_test(tt); fflush(stdout);
- retval |= test_incomplete(tt); fflush(stdout);
- retval |= reuse_test(tt); fflush(stdout);
- retval |= tls_test(tt); fflush(stdout);
- if (0) /* Not yet working... */
- retval |= stun_test(tt); fflush(stdout);
- retval |= deinit_test(tt); fflush(stdout);
- }
- su_deinit();
- #if HAVE_OPEN_C
- sleep(10);
- #endif
- return retval;
- }
|