# $Id: ping.tcl 1259 2007-10-07 15:37:45Z sergei $
# Reply to XMPP Ping (XEP-0199) support

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

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

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

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

    variable sequence

    iq::register_handler get query urn:xmpp:ping [namespace current]::reply
    hook::add connected_hook [namespace current]::start
}

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

proc ping::reply {connid from lang child} {
    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 connid [jlib::connections] {
	start $connid
    }
}

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

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

    after cancel [list [namespace current]::start $connid]

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

    if {![info exists sequence($connid)]} {
	set sequence($connid) 0
    } else {
	incr sequence($connid)
    }

    jlib::send_iq get \
	[jlib::wrapper:createtag ping \
	     -vars [list xmlns urn:xmpp:ping]] \
	-timeout [expr {$options(timeout)*1000}] \
	-connection $connid \
	-command [list [namespace current]::result $connid $sequence($connid)]
}

proc ping::result {connid seq res child} {
    variable options
    variable sequence

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

    if {![lcontain [jlib::connections] $connid]} return

    if {$res == "DISCONNECT"} return

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

    if {$res == "TIMEOUT"} {
	# TODO
	jlib::inmsg $connid "" 1
	return
    }

    after [expr {$options(timeout)*1000}] \
	  [list [namespace current]::start $connid]
}

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

