Commit 1fc68c70 authored by Simon Morlat's avatar Simon Morlat

implement keepalive on tls tport, on the model what is done for tcp.

parent 6d266426
......@@ -521,11 +521,6 @@ ssize_t tport_send_stream(tport_t const *self, msg_t *msg,
int tport_tcp_next_timer(tport_t *self, su_time_t *, char const **);
void tport_tcp_timer(tport_t *self, su_time_t);
int tport_next_recv_timeout(tport_t *, su_time_t *, char const **);
void tport_recv_timeout_timer(tport_t *self, su_time_t now);
int tport_next_keepalive(tport_t *self, su_time_t *, char const **);
void tport_keepalive_timer(tport_t *self, su_time_t now);
extern tport_vtable_t const tport_sctp_vtable;
extern tport_vtable_t const tport_sctp_client_vtable;
......
......@@ -443,7 +443,7 @@ int tport_next_keepalive(tport_t *self,
/** Keepalive timer. */
void tport_keepalive_timer(tport_t *self, su_time_t now)
static void tport_keepalive_timer(tport_t *self, su_time_t now)
{
unsigned timeout = self->tp_params->tpp_pingpong;
......
......@@ -96,6 +96,12 @@ static int tport_tls_accept(tport_primary_t *pri, int events);
static tport_t *tport_tls_connect(tport_primary_t *pri, su_addrinfo_t *ai,
tp_name_t const *tpn);
static int tport_tls_ping(tport_t *self, su_time_t now);
static void tport_tls_timer(tport_t *self, su_time_t now);
static int tport_tls_next_timer(tport_t *self,
su_time_t *return_target,
char const **return_why);
tport_vtable_t const tport_tls_vtable =
{
/* vtp_name */ "tls",
......@@ -117,8 +123,8 @@ tport_vtable_t const tport_tls_vtable =
/* vtp_prepare */ NULL,
/* vtp_keepalive */ NULL,
/* vtp_stun_response */ NULL,
/* vtp_next_secondary_timer*/ NULL,
/* vtp_secondary_timer */ NULL,
/* vtp_next_secondary_timer*/ tport_tls_next_timer,
/* vtp_secondary_timer */ tport_tls_timer,
};
tport_vtable_t const tport_tls_client_vtable =
......@@ -142,8 +148,8 @@ tport_vtable_t const tport_tls_client_vtable =
/* vtp_prepare */ NULL,
/* vtp_keepalive */ NULL,
/* vtp_stun_response */ NULL,
/* vtp_next_secondary_timer*/ NULL,
/* vtp_secondary_timer */ NULL,
/* vtp_next_secondary_timer*/ tport_tls_next_timer,
/* vtp_secondary_timer */ tport_tls_timer,
};
static int tport_tls_init_primary(tport_primary_t *pri,
......@@ -698,3 +704,190 @@ sys_error:
su_seterrno(err);
return NULL;
}
/** Calculate timeout if receive is incomplete. */
static int tport_next_recv_timeout(tport_t *self,
su_time_t *return_target,
char const **return_why)
{
unsigned timeout = self->tp_params->tpp_timeout;
if (timeout < INT_MAX) {
/* Recv timeout */
if (self->tp_msg) {
su_time_t ntime = su_time_add(self->tp_rtime, timeout);
if (su_time_cmp(ntime, *return_target) < 0)
*return_target = ntime, *return_why = "recv timeout";
}
#if 0
/* Send timeout */
if (tport_has_queued(self)) {
su_time_t ntime = su_time_add(self->tp_stime, timeout);
if (su_time_cmp(ntime, *return_target) < 0)
*return_target = ntime, *return_why = "send timeout";
}
#endif
}
return 0;
}
/** Timeout timer if receive is incomplete */
static void tport_recv_timeout_timer(tport_t *self, su_time_t now)
{
unsigned timeout = self->tp_params->tpp_timeout;
if (timeout < INT_MAX) {
if (self->tp_msg &&
su_time_cmp(su_time_add(self->tp_rtime, timeout), now) < 0) {
msg_t *msg = self->tp_msg;
msg_set_streaming(msg, (enum msg_streaming_status)0);
msg_set_flags(msg, MSG_FLG_ERROR | MSG_FLG_TRUNC | MSG_FLG_TIMEOUT);
tport_deliver(self, msg, NULL, NULL, now);
self->tp_msg = NULL;
}
#if 0
/* Send timeout */
if (tport_has_queued(self) &&
su_time_cmp(su_time_add(self->tp_stime, timeout), now) < 0) {
stime = su_time_add(self->tp_stime, self->tp_params->tpp_timeout);
if (su_time_cmp(stime, target) < 0)
target = stime;
}
#endif
}
}
/** Calculate next timeout for keepalive */
static int tport_next_keepalive(tport_t *self,
su_time_t *return_target,
char const **return_why)
{
/* Keepalive timer */
unsigned timeout = self->tp_params->tpp_keepalive;
if (timeout != 0 && timeout != UINT_MAX) {
if (!tport_has_queued(self)) {
su_time_t ntime = su_time_add(self->tp_ktime, timeout);
if (su_time_cmp(ntime, *return_target) < 0)
*return_target = ntime, *return_why = "keepalive";
}
}
timeout = self->tp_params->tpp_pingpong;
if (timeout != 0) {
if (self->tp_ptime.tv_sec && !self->tp_recv_close) {
su_time_t ntime = su_time_add(self->tp_ptime, timeout);
if (su_time_cmp(ntime, *return_target) < 0)
*return_target = ntime, *return_why = "waiting for pong";
}
}
return 0;
}
/** Keepalive timer. */
static void tport_keepalive_timer(tport_t *self, su_time_t now)
{
unsigned timeout = self->tp_params->tpp_pingpong;
if (timeout != 0) {
if (self->tp_ptime.tv_sec && !self->tp_recv_close &&
su_time_cmp(su_time_add(self->tp_ptime, timeout), now) < 0) {
SU_DEBUG_3(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
"closing connection", TPN_ARGS(self->tp_name),
" because of PONG timeout"));
tport_error_report(self, EPIPE, NULL);
if (!self->tp_closed)
tport_close(self);
return;
}
}
timeout = self->tp_params->tpp_keepalive;
if (timeout != 0 && timeout != UINT_MAX) {
if (su_time_cmp(su_time_add(self->tp_ktime, timeout), now) < 0) {
tport_tls_ping(self, now);
}
}
}
/** Send PING */
static int tport_tls_ping(tport_t *self, su_time_t now)
{
ssize_t n;
char *why = "";
tport_tls_t *tlstp = (tport_tls_t*)self;
if (tport_has_queued(self))
return 0;
n = tls_write(tlstp->tlstp_context, "\r\n\r\n", 4);
if (n == -1) {
int error = su_errno();
why = " failed";
if (!su_is_blocking(error))
tport_error_report(self, error, NULL);
else
why = " blocking";
return -1;
}
if (n > 0)
self->tp_ktime = now;
if (n == 4) {
if (self->tp_ptime.tv_sec == 0)
self->tp_ptime = now;
}
SU_DEBUG_2(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
"sending PING", TPN_ARGS(self->tp_name), why));
return 0;
}
/** Send pong */
static int tport_tls_pong(tport_t *self)
{
tport_tls_t *tlstp = (tport_tls_t*)self;
self->tp_ping = 0;
if (tport_has_queued(self) || !self->tp_params->tpp_pong2ping)
return 0;
SU_DEBUG_2(("%s(%p): %s to " TPN_FORMAT "%s\n",
__func__, (void *)self,
"sending PONG", TPN_ARGS(self->tp_name), ""));
return tls_write(tlstp->tlstp_context, "\r\n", 2);
}
/** Calculate next timer for TCP. */
static int tport_tls_next_timer(tport_t *self,
su_time_t *return_target,
char const **return_why)
{
return
tport_next_recv_timeout(self, return_target, return_why) |
tport_next_keepalive(self, return_target, return_why);
}
/** TCP timer. */
static void tport_tls_timer(tport_t *self, su_time_t now)
{
tport_recv_timeout_timer(self, now);
tport_keepalive_timer(self, now);
tport_base_timer(self, now);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment