1 ;; jabber-keepalive.el - try to detect lost connection -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2004, 2008 - Magnus Henoch - mange@freemail.hu
4 ;; Copyright (C) 2007 - Detlev Zundel - dzu@gnu.org
6 ;; This file is a part of jabber.el.
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2 of the License, or
11 ;; (at your option) any later version.
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program; if not, write to the Free Software
20 ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 ;;;; Keepalive - send something to the server and see if it answers
25 ;;; These keepalive functions send a urn:xmpp:ping request to the
26 ;;; server every X minutes, and considers the connection broken if
27 ;;; they get no answer within Y seconds.
29 (require 'jabber-ping)
32 (defgroup jabber-keepalive nil
33 "Keepalive functions try to detect lost connection"
36 (defcustom jabber-keepalive-interval 600
37 "Interval in seconds between connection checks."
39 :group 'jabber-keepalive)
41 (defcustom jabber-keepalive-timeout 20
42 "Seconds to wait for response from server."
44 :group 'jabber-keepalive)
46 (defvar jabber-keepalive-timer nil
47 "Timer object for keepalive function.")
49 (defvar jabber-keepalive-timeout-timer nil
50 "Timer object for keepalive timeout function.")
52 (defvar jabber-keepalive-pending nil
53 "List of outstanding keepalive connections.")
55 (defvar jabber-keepalive-debug nil
56 "Log keepalive traffic when non-nil.")
59 (defun jabber-keepalive-start (&optional jc)
61 That is, regularly send a ping request to the server, and
62 disconnect it if it doesn't answer. See variable `jabber-keepalive-interval'
63 and variable `jabber-keepalive-timeout'.
65 The JC argument makes it possible to add this function to
66 `jabber-post-connect-hooks'; it is ignored. Keepalive is activated
67 for all accounts regardless of the argument."
70 (when jabber-keepalive-timer
71 (jabber-keepalive-stop))
73 (setq jabber-keepalive-timer
75 jabber-keepalive-interval
76 'jabber-keepalive-do))
77 (add-hook 'jabber-post-disconnect-hook 'jabber-keepalive-stop))
79 (defun jabber-keepalive-stop ()
80 "Deactivate keepalive."
83 (when jabber-keepalive-timer
84 (jabber-cancel-timer jabber-keepalive-timer)
85 (setq jabber-keepalive-timer nil)))
87 (defun jabber-keepalive-do ()
88 (when jabber-keepalive-debug
89 (message "%s: sending keepalive packet(s)" (current-time-string)))
90 (setq jabber-keepalive-timeout-timer
91 (run-with-timer jabber-keepalive-timeout
93 'jabber-keepalive-timeout))
94 (setq jabber-keepalive-pending jabber-connections)
95 (dolist (c jabber-connections)
96 ;; Whether we get an error or not is not interesting.
97 ;; Getting a response at all is.
98 (jabber-ping-send c nil 'jabber-keepalive-got-response nil nil)))
100 (defun jabber-keepalive-got-response (jc &rest args)
101 (when jabber-keepalive-debug
102 (message "%s: got keepalive response from %s"
103 (current-time-string)
104 (plist-get (fsm-get-state-data jc) :server)))
105 (setq jabber-keepalive-pending (remq jc jabber-keepalive-pending))
106 (when (and (null jabber-keepalive-pending) (timerp jabber-keepalive-timeout-timer))
107 (jabber-cancel-timer jabber-keepalive-timeout-timer)
108 (setq jabber-keepalive-timeout-timer nil)))
110 (defun jabber-keepalive-timeout ()
111 (jabber-cancel-timer jabber-keepalive-timer)
112 (setq jabber-keepalive-timer nil)
114 (dolist (c jabber-keepalive-pending)
115 (message "%s: keepalive timeout, connection to %s considered lost"
116 (current-time-string)
117 (plist-get (fsm-get-state-data c) :server))
119 (run-hook-with-args 'jabber-lost-connection-hooks c)
120 (jabber-disconnect-one c nil)))
122 ;;;; Whitespace pings - less traffic, no error checking on our side
124 ;;; Openfire needs something like this, but I couldn't bring myself to
125 ;;; enable keepalive by default... Whitespace pings are light and
128 (defcustom jabber-whitespace-ping-interval 30
129 "Send a space character to the server with this interval, in seconds.
131 This is a traditional remedy for a number of problems: to keep NAT
132 boxes from considering the connection dead, to have the OS discover
133 earlier that the connection is lost, and to placate servers which rely
134 on the client doing this, e.g. Openfire.
136 If you want to verify that the server is able to answer, see
137 `jabber-keepalive-start' for another mechanism."
138 :type '(integer :tag "Interval in seconds")
141 (defvar jabber-whitespace-ping-timer nil
142 "Timer object for whitespace pings.")
145 (defun jabber-whitespace-ping-start (&optional jc)
146 "Start sending whitespace pings at regular intervals.
147 See `jabber-whitespace-ping-interval'.
149 The JC argument is ignored; whitespace pings are enabled for all
153 (when jabber-whitespace-ping-timer
154 (jabber-whitespace-ping-stop))
156 (setq jabber-whitespace-ping-timer
158 jabber-whitespace-ping-interval
159 'jabber-whitespace-ping-do))
160 (add-hook 'jabber-post-disconnect-hook 'jabber-whitespace-ping-stop))
162 (defun jabber-whitespace-ping-stop ()
163 "Deactivate whitespace pings."
166 (when jabber-whitespace-ping-timer
167 (jabber-cancel-timer jabber-whitespace-ping-timer)
168 (setq jabber-whitespace-ping-timer nil)))
170 (defun jabber-whitespace-ping-do ()
171 (dolist (c jabber-connections)
172 (ignore-errors (jabber-send-string c " "))))
174 (provide 'jabber-keepalive)
176 ;;; arch-tag: d19ca743-75a1-475f-9217-83bd18012146