# $Id: ping.tcl 1831 2009-08-11 20:02:09Z sergei $
# XMPP Ping (XEP-0199) support

#############################################################################

package require xmpp::ping

namespace eval ping {
    custom::defvar options(ping) 0 \
	[::msgcat::mc "Ping server using XMPP ping requests."] \
	-group IQ \
	-type boolean \
	-command [namespace code start_all]

    custom::defvar options(timeout) 30 \
	[::msgcat::mc "Reconnect to server if it does not reply (with result\
		       or with error) to XMPP ping request in\
		       specified time interval (in seconds)."] \
	-group IQ \
	-type integer \
	-command [namespace code start_all]

    custom::defvar options(pong) 0 \
	[::msgcat::mc "Reply to XMPP ping requests."] \
	-group IQ \
	-type boolean

    variable sequence

    ::xmpp::ping::register -command [namespace code reply]
    hook::add connected_hook [namespace code start]
}

#############################################################################

proc ping::reply {xlib from args} {
    variable options

    if {$options(pong)} {
	return [list result {}]
    } else {
	return [list error cancel service-unavailable]
    }
}

#############################################################################

proc ping::start_all {args} {
    variable options

    if {!$options(ping) || ($options(timeout) <= 0)} return

    foreach xlib [connections] {
	start $xlib
    }
}

#############################################################################

proc ping::start {xlib} {
    variable options
    variable sequence

    after cancel [namespace code [list start $xlib]]

    if {!$options(ping) || ($options(timeout) <= 0)} return

    if {![info exists sequence($xlib)]} {
	set sequence($xlib) 0
    }

    ::xmpp::ping::ping $xlib \
	    -timeout [expr {$options(timeout)*1000}] \
	    -command [namespace code [list result $xlib [incr sequence($xlib)]]]
}

proc ping::result {xlib seq status xml} {
    variable options
    variable sequence

    if {!$options(ping) || ($options(timeout) <= 0)} return

    if {[lsearch -exact [connections] $xlib] < 0} return

    if {[string equal $status abort]} return

    if {$seq < $sequence($xlib)} return

    if {[string equal $status timeout]} {
	::xmpp::EndOfFile $xlib
	return
    }

    after [expr {$options(timeout)*1000}] [namespace code [list start $xlib]]
}

#############################################################################

