Commit d65fd637 authored by Pekka Pessi's avatar Pekka Pessi

tport: added ping-pong keepalive on TCP. replaced single tick with connection-specific timer

Now detecting closed connections on TLS, too.

Added tests for idle timeout, receive timeout, ping-pong timeout.

darcs-hash:20070725160906-65a35-0d568677e950abbc55b7ab10ae9a1fc8000155e6.gz
parent cad60e04
......@@ -33,6 +33,9 @@
* @date Created: Wed Apr 3 11:25:13 2002 ppessi
*/
/* always assert()s */
#undef NDEBUG
#include "config.h"
#include <stddef.h>
......@@ -49,6 +52,8 @@ typedef struct tp_test_s tp_test_t;
#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"
......@@ -101,6 +106,9 @@ struct tp_test_s {
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;
......@@ -359,7 +367,11 @@ static void tp_test_recv(tp_test_t *tt,
tt->tt_status = 1;
tt->tt_received++;
if (test_msg_md5(tt, msg))
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);
......@@ -451,7 +463,7 @@ tp_stack_class_t const tp_test_class[1] =
static int init_test(tp_test_t *tt)
{
tp_name_t myname[1] = {{ "*", "*", "*", "*", "sigcomp" }};
#if HAVE_NETINET_SCTP_H
#if HAVE_SCTP
char const * transports[] = { "udp", "tcp", "sctp", NULL };
#else
char const * transports[] = { "udp", "tcp", NULL };
......@@ -635,7 +647,7 @@ static int init_test(tp_test_t *tt)
for (tp = tport_primaries(tt->tt_srv_tports); tp; tp = tport_next(tp)) {
TEST_1(tpn = tport_name(tp));
if (1 || tt->tt_flags & tst_verbatim) {
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,
......@@ -661,6 +673,11 @@ static int init_test(tp_test_t *tt)
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;
......@@ -738,7 +755,7 @@ static int udp_test(tp_test_t *tt)
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);
......@@ -778,23 +795,72 @@ static int udp_test(tp_test_t *tt)
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();
#ifndef WIN32 /* Windows seems to be buffering too much */
msg_t *msg = NULL;
int i;
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);
#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()));
TEST_S(tport_name(tp)->tpn_ident, "client");
tp0 = tport_incref(tp);
TEST_P(tport_incref(tp), tp0); tport_decref(&tp);
msg_destroy(msg);
/* Fill up the queue */
......@@ -827,10 +893,12 @@ static int tcp_test(tp_test_t *tt)
msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
}
#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()));
TPTAG_REUSE(0), TAG_END()));
TEST_S(tport_name(tp)->tpn_ident, "client");
TEST_1(tport_incref(tp) != tp0); tport_decref(&tp);
msg_destroy(msg);
......@@ -838,7 +906,7 @@ static int tcp_test(tp_test_t *tt)
/* 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()));
TPTAG_REUSE(1), TAG_END()));
TEST_S(tport_name(tp)->tpn_ident, "client");
TEST_1(tport_incref(tp) == tp0); tport_decref(&tp);
msg_destroy(msg);
......@@ -863,9 +931,99 @@ static int tcp_test(tp_test_t *tt)
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);
#endif
/* 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);
connected = connect(s, ai->ai_addr, ai->ai_addrlen);
su_root_step(tt->tt_root, 50);
TEST(send(s, "F", 1, 0), 1);
su_root_step(tt->tt_root, 50);
TEST(send(s, "O", 1, 0), 1);
su_root_step(tt->tt_root, 50);
TEST(send(s, "O", 1, 0), 1);
su_root_step(tt->tt_root, 50);
TEST(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();
}
......@@ -967,34 +1125,48 @@ static int sctp_test(tp_test_t *tt)
msg_t *msg = NULL;
int i, n;
tport_t *tp;
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, "sctp-small", 1, 1024));
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;
if (1)
return 0; /* SCTP does not work reliably. Really. */
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(tport_tsend(tp, msg, tt->tt_sctp_name, TAG_END()));
TEST_1(tp = tport_tsend(tp0, msg, tt->tt_sctp_name, TAG_END()));
TEST_S(tport_name(tp)->tpn_ident, "client");
msg_destroy(msg);
}
......@@ -1003,11 +1175,11 @@ static int sctp_test(tp_test_t *tt)
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(tport_tsend(tp, msg, tt->tt_sctp_name, TAG_END()));
TEST_1(tp = tport_tsend(tp0, msg, tt->tt_sctp_name, TAG_END()));
msg_destroy(msg);
}
/* This overflows the queue */
/* 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()));
......@@ -1020,13 +1192,13 @@ static int sctp_test(tp_test_t *tt)
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(!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 = 0; tt->tt_received < TPORT_QUEUESIZE + n;) {
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));
......@@ -1034,7 +1206,7 @@ static int sctp_test(tp_test_t *tt)
}
/* Try to send a single message */
TEST_1(!new_test_msg(tt, &msg, "cid:sctp-final", 1, 1024));
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);
......@@ -1042,6 +1214,15 @@ static int sctp_test(tp_test_t *tt)
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();
}
......@@ -1055,15 +1236,35 @@ static int tls_test(tp_test_t *tt)
msg_t *msg = NULL;
int i;
char ident[16];
tport_t *tp, *tp0;
TEST_S(dst->tpn_proto, "tls");
tt->tt_received = 0;
/* 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));
msg_destroy(msg);
/* Create a large message, just to force queueing in sending end */
TEST_1(!new_test_msg(tt, &msg, "tls-0", 16, 64 * 1024));
TEST(tport_test_run(tt, 5), 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(tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
TEST_1(tp == tp0);
msg_destroy(msg);
/* Fill up the queue */
......@@ -1071,25 +1272,20 @@ static int tls_test(tp_test_t *tt)
snprintf(ident, sizeof ident, "tls-%u", i);
TEST_1(!new_test_msg(tt, &msg, ident, 2, 512));
TEST_1(tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
TEST_1(tp == tp0);
msg_destroy(msg);
}
/* This overflows the queue */
TEST_1(!new_test_msg(tt, &msg, "tls-overflow", 1, 1024));
TEST_1(!tport_tsend(tt->tt_tports, msg, dst, TAG_END()));
msg_destroy(msg);
TEST(tport_test_run(tt, 60), 1);
msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL;
/* This uses a new connection */
TEST_1(!new_test_msg(tt, &msg, "tls-no-reuse", 1, 1024));
TEST_1(tport_tsend(tt->tt_tports, msg, dst,
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);
......@@ -1107,6 +1303,14 @@ static int tls_test(tp_test_t *tt)
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();
......@@ -1363,9 +1567,24 @@ static int filter_test(tp_test_t *tt)
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]\n", name);
fprintf(stderr, "usage: %s [-v] [-a]%s\n", name, alarm_option);
exit(exitcode);
}
......@@ -1373,7 +1592,9 @@ 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++) {
......@@ -1381,6 +1602,8 @@ int main(int argc, char *argv[])
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);
}
......@@ -1389,6 +1612,13 @@ int main(int argc, char *argv[])
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;
......@@ -1406,6 +1636,7 @@ int main(int argc, char *argv[])
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... */
......
......@@ -47,7 +47,7 @@
typedef struct tport_nat_s tport_nat_t;
#define SU_WAKEUP_ARG_T struct tport_s
#define SU_TIMER_ARG_T struct tport_master
#define SU_TIMER_ARG_T struct tport_s
#define SU_MSG_ARG_T union tport_su_msg_arg
#include <sofia-sip/su_wait.h>
......@@ -127,6 +127,33 @@ RBTREE_BODIES(su_inline, tprb, tport_t,
TP_IS_RED, TP_SET_RED, TP_IS_BLACK, TP_SET_BLACK, TP_COPY_COLOR,
tp_cmp, TP_INSERT, TP_REMOVE);
static void tplist_insert(tport_t **list, tport_t *tp)
{
if (*list == NULL)
*list = tp;
else
tp->tp_right = *list, (*list)->tp_left = tp, *list = tp;
for (tp = *list; tp; tp = tp->tp_right) {
assert(tp->tp_left == NULL || tp == tp->tp_left->tp_right);
assert(tp->tp_right == NULL || tp == tp->tp_right->tp_left);
}
}
static void tplist_remove(tport_t **list, tport_t *tp)
{
if (*list == tp) {
*list = tp->tp_right; assert(tp->tp_left == NULL);
}
else if (tp->tp_left) {
tp->tp_left->tp_right = tp->tp_right;
}
if (tp->tp_right) {
tp->tp_right->tp_left = tp->tp_left;
}
TP_REMOVE(tp);
}
enum {
/** Default per-thread read queue length */
THRP_PENDING = 8
......@@ -304,6 +331,12 @@ int tport_is_clear_to_send(tport_t const *self)
!self->tp_send_close);
}
/** Return true if transport has message in send queue. @NEW_1_12_7 */
int tport_has_queued(tport_t const *self)
{
return self && self->tp_queue && self->tp_queue[self->tp_qhead];
}
/** MTU for transport */
su_inline unsigned tport_mtu(tport_t const *self)
{
......@@ -387,9 +420,6 @@ tport_t *tport_by_addrinfo(tport_primary_t const *pri,
tp_name_t const *tpn);
void tport_peer_address(tport_t *self, msg_t *msg);
static unsigned long tport_now(void);
static void tport_tick(su_root_magic_t *, su_timer_t *, tport_master_t *mr);
static void tport_parse(tport_t *self, int complete, su_time_t now);
......@@ -410,7 +440,6 @@ static void tport_zap_primary(tport_primary_t *);
static char *localipname(int pf, char *buf, size_t bufsiz);
static int getprotohints(su_addrinfo_t *hints,
char const *proto, int flags);
static void tport_send_queue(tport_t *self);
/* Stack class used when transports are being destroyed */
......@@ -454,7 +483,6 @@ tport_t *tport_tcreate(tp_stack_t *stack,
tport_master_t *mr;
tp_name_t *tpn;
tport_params_t *tpp;
unsigned tick;
ta_list ta;
if (!stack || !tpac || !root) {
......@@ -500,21 +528,10 @@ tport_t *tport_tcreate(tp_stack_t *stack,
tport_set_params(mr->mr_master, ta_tags(ta));
tport_open_log(mr, ta_args(ta));
tick = 5000; /* For testing, usually 30000 is enough */
if (tpp->tpp_idle < 4 * tick)
tick = tpp->tpp_idle / 4;
if (tpp->tpp_timeout < 4 * tick)
tick = tpp->tpp_timeout / 4;
if (tick < 200)
tick = 200;
#if HAVE_SOFIA_STUN
tport_init_stun_server(mr, ta_args(ta));
#endif
mr->mr_timer = su_timer_create(su_root_task(root), tick);
su_timer_set(mr->mr_timer, tport_tick, mr);
ta_end(ta);
return mr->mr_master;
......@@ -643,8 +660,10 @@ void tport_zap_primary(tport_primary_t *pri)
if (pri->pri_vtable->vtp_deinit_primary)
pri->pri_vtable->vtp_deinit_primary(pri);
while (pri->pri_secondary)
tport_zap_secondary(pri->pri_secondary);
while (pri->pri_open)
tport_zap_secondary(pri->pri_open);
while (pri->pri_closed)
tport_zap_secondary(pri->pri_closed);
/* We have just a single-linked list for primary transports */
for (prip = &pri->pri_master->mr_primaries;
......@@ -654,7 +673,7 @@ void tport_zap_primary(tport_primary_t *pri)
*prip = pri->pri_next;
tport_zap_secondary(pri->pri_primary);
tport_zap_secondary((tport_t *)pri);
}
/**Create a primary transport object with socket.
......@@ -815,9 +834,8 @@ int tport_set_events(tport_t *self, int set, int clear)
/**Allocate a secondary transport. @internal
*
* The function tport_alloc_secondary() creates a secondary transport
* object. The new transport initally shares parameters structure with the
* original transport.
* Create a secondary transport object. The new transport initally shares
* parameters structure with the original transport.
*
* @param pri primary transport
* @param socket socket for transport
......@@ -854,7 +872,10 @@ tport_t *tport_alloc_secondary(tport_primary_t *pri,
self->tp_addrinfo->ai_addr = (void *)self->tp_addr;
self->tp_socket = socket;
self->tp_timer = su_timer_create(su_root_task(mr->mr_root), 0);
self->tp_stime = self->tp_ktime = self->tp_rtime = su_now();
if (pri->pri_vtable->vtp_init_secondary &&
pri->pri_vtable->vtp_init_secondary(self, socket, accepted,
return_reason) < 0) {
......@@ -893,13 +914,18 @@ tport_t *tport_connect(tport_primary_t *pri,
su_addrinfo_t *ai,
tp_name_t const *tpn)
{
tport_t *tp;
if (ai == NULL || ai->ai_addrlen > sizeof (pri->pri_primary->tp_addr))
return NULL;
if (pri->pri_vtable->vtp_connect)
return pri->pri_vtable->vtp_connect(pri, ai, tpn);
else
return tport_base_connect(pri, ai, ai, tpn);
tp = tport_base_connect(pri, ai, ai, tpn);
if (tp)
tport_set_secondary_timer(tp);
return tp;
}
/**Create a connected transport object with socket.
......@@ -1017,8 +1043,8 @@ tport_t *tport_base_connect(tport_primary_t *pri,
tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr, 2),
TPN_ARGS(self->tp_name)));
}
tprb_append(&pri->pri_secondary, self);
tprb_append(&pri->pri_open, self);
return self;
}
......@@ -1032,7 +1058,13 @@ void tport_zap_secondary(tport_t *self)
return;
/* Remove from rbtree */
tprb_remove(&self->tp_pri->pri_secondary, self);
if (!tport_is_closed(self))
tprb_remove(&self->tp_pri->pri_open, self);
else
tplist_remove(&self->tp_pri->pri_closed, self);