emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master f5ebe47ba77 1/2: Reuse process in erc-server-delayed-check-reconn


From: F. Jason Park
Subject: master f5ebe47ba77 1/2: Reuse process in erc-server-delayed-check-reconnect
Date: Fri, 27 Dec 2024 18:22:59 -0500 (EST)

branch: master
commit f5ebe47ba7723919f09adf8f28d896cfa8757842
Author: F. Jason Park <jp@neverwas.me>
Commit: F. Jason Park <jp@neverwas.me>

    Reuse process in erc-server-delayed-check-reconnect
    
    * doc/misc/erc.texi (Integrations): Set `erc-server-reconnect-function'
    to `erc-server-delayed-check-reconnect' in SOCKS example, and add
    definition for `erc-open-socks-tls-stream'.  Mention possible
    inaccuracies related to error detection with certain reconnect
    strategies.
    * lisp/erc/erc-backend.el (erc-server--reconnect-opened): New function.
    (erc-server-delayed-check-reconnect): Attempt to reuse process if server
    sends a complete PONG, and attempt to accommodate connectors that set
    :nowait to nil.
    (erc--server-delayed-check-connectors): Remove variable.
    (erc-server-prefer-check-reconnect): Inline what was the internal
    variable `erc--server-delayed-check-connectors' because it's no longer
    used in unit tests.  Add `erc-open-socks-tls-stream' to the set of
    connector functions thought to be compatible with the "check" reconnect
    strategy.
    * test/lisp/erc/erc-scenarios-base-auto-recon.el
    (erc-scenarios-base-auto-recon-no-proto): Adapt to expect "reuse" behavior.
    * test/lisp/erc/resources/base/reconnect/ping-pong.eld: Delete unused file.
    * test/lisp/erc/resources/base/reconnect/unexpected-disconnect.eld:
    Capture PING cookie to send back to client.
    * test/lisp/erc/resources/erc-d/resources/proxy-solo.eld: Delete unused
    file.  (Bug#62044)
---
 doc/misc/erc.texi                                  | 14 +++++
 lisp/erc/erc-backend.el                            | 62 +++++++++++++++-------
 test/lisp/erc/erc-scenarios-base-auto-recon.el     |  3 +-
 .../erc/resources/base/reconnect/ping-pong.eld     |  6 ---
 .../base/reconnect/unexpected-disconnect.eld       |  3 +-
 .../erc/resources/erc-d/resources/proxy-solo.eld   |  9 ----
 6 files changed, 62 insertions(+), 35 deletions(-)

diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index b5838b3b0ce..0045691a230 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -1667,6 +1667,8 @@ shown in the following example:
         (socks-server '("tor" "localhost" 9050 5)))
     (apply #'erc-open-socks-tls-stream args)))
 
+(setopt erc-server-reconnect-function #'erc-server-delayed-check-reconnect)
+
 (let* ((erc-modules (cons 'sasl erc-modules))
        (erc-sasl-mechanism 'external)
        (erc-server-connect-function #'my-erc-open-socks-tls-stream))
@@ -1687,6 +1689,18 @@ with ERC exclusively, you can just set those options and 
variables
 globally and bind @code{erc-server-connect-function} to
 @code{erc-open-socks-tls-stream} instead.
 
+@defun erc-open-socks-tls-stream
+The default TLS @dfn{connector} for @acronym{SOCKS} connections.
+Compatible with option @code{erc-server-connect-function}.  Be aware
+that if used in conjunction with certain values of
+@code{erc-server-reconnect-function} (such as
+@code{erc-server-prefer-check-reconnect}, currently the default
+@dfn{reconnector}, or @code{erc-server-delayed-check-reconnect}, the
+more specialized workhorse it defers to), this function may cause ERC to
+misreport proxy-related failures as routine lapses in internet
+connectivity.
+@end defun
+
 @node auth-source
 @subsection auth-source
 @cindex auth-source
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index ab26a3715f1..098cf6d7d71 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -830,6 +830,13 @@ Make sure you are in an ERC buffer when running this."
     (with-current-buffer buffer
       (erc-server-reconnect))))
 
+(defun erc-server--reconnect-opened (buffer process)
+  "Reconnect session for server BUFFER using open PROCESS."
+  (when (buffer-live-p buffer)
+    (with-current-buffer buffer
+      (let ((erc-session-connector (lambda (&rest _) process)))
+        (erc-server-reconnect)))))
+
 (defvar-local erc--server-reconnect-timeout nil)
 (defvar-local erc--server-reconnect-timeout-check 10)
 (defvar-local erc--server-reconnect-timeout-scale-function
@@ -845,7 +852,13 @@ Make sure you are in an ERC buffer when running this."
 
 (defun erc-server-delayed-check-reconnect (buffer)
   "Wait for internet connectivity before trying to reconnect.
-Expect BUFFER to be the server buffer for the current connection."
+Use server BUFFER's cached session info to reestablish the logical
+connection at the IRC protocol level.  Do this by probing for a
+successful response to a PING before commencing with \"connection
+registration\".  Do not distinguish between configuration problems and
+the absence of service.  For example, expect users of proxy-based
+connectors, like `erc-open-socks-tls-stream', to ensure their setup
+works before choosing this function as their reconnector."
   (when (buffer-live-p buffer)
     (with-current-buffer buffer
       (setq erc--server-reconnect-timeout
@@ -857,7 +870,8 @@ Expect BUFFER to be the server buffer for the current 
connection."
                              (with-current-buffer buffer
                                (let ((erc-server-reconnect-timeout
                                       erc--server-reconnect-timeout))
-                                 (delete-process proc)
+                                 (when proc ; conn refused w/o :nowait
+                                   (delete-process proc))
                                  (erc-display-message nil 'error buffer
                                                       "Nobody home...")
                                  (erc-schedule-reconnect buffer 0))))))
@@ -867,7 +881,7 @@ Expect BUFFER to be the server buffer for the current 
connection."
              (conchk (lambda (proc)
                        (let ((status (process-status proc))
                              (xprdp (time-less-p conchk-exp (current-time))))
-                         (when (or (not (eq 'connect status)) xprdp)
+                         (when (or xprdp (not (eq 'connect status)))
                            (cancel-timer conchk-timer))
                          (when (buffer-live-p buffer)
                            (cond (xprdp (erc-display-message
@@ -880,38 +894,50 @@ Expect BUFFER to be the server buffer for the current 
connection."
              (sentinel (lambda (proc event)
                          (pcase event
                            ("open\n"
-                            (run-at-time nil nil #'process-send-string proc
-                                         (format "PING %d\r\n"
-                                                 (time-convert nil 'integer))))
+                            (let ((cookie (time-convert nil 'integer)))
+                              (process-put proc 'erc--reconnect-cookie cookie)
+                              (run-at-time nil nil #'process-send-string proc
+                                           (format "PING %d\r\n" cookie))))
                            ((or "connection broken by remote peer\n"
                                 (rx bot "failed"))
                             (run-at-time nil nil reschedule proc)))))
-             (filter (lambda (proc _)
-                       (delete-process proc)
+             (filter (lambda (proc string)
                        (with-current-buffer buffer
                          (setq erc--server-reconnect-timeout nil))
-                       (run-at-time nil nil #'erc-server-delayed-reconnect
-                                    buffer))))
+                       (if-let* ; reuse proc if string has complete message
+                           ((cookie (process-get proc 'erc--reconnect-cookie))
+                            ((string-suffix-p (format "PONG %d\r\n" cookie)
+                                              string))) ; leading ":<source> "
+                           (progn
+                             (erc-log-irc-protocol string nil)
+                             (set-process-sentinel proc #'ignore)
+                             (set-process-filter proc nil)
+                             (run-at-time nil nil
+                                          #'erc-server--reconnect-opened
+                                          buffer proc))
+                         (delete-process proc)
+                         (run-at-time nil nil #'erc-server-delayed-reconnect
+                                      buffer)))))
         (condition-case _
             (let ((proc (funcall erc-session-connector
                                  "*erc-connectivity-check*" nil
-                                 erc-session-server erc-session-port
-                                 :nowait t)))
+                                 erc-session-server erc-session-port)))
               (setq conchk-timer (run-at-time 1 1 conchk proc))
               (set-process-filter proc filter)
-              (set-process-sentinel proc sentinel))
+              (set-process-sentinel proc sentinel)
+              (when (eq (process-status proc) 'open) ; :nowait is nil
+                (funcall sentinel proc "open\n")))
+          ;; E.g., "make client process failed" "Connection refused".
           (file-error (funcall reschedule nil)))))))
 
-(defvar erc--server-delayed-check-connectors
-  '(erc-open-tls-stream erc-open-network-stream)
-  "Functions compatible with `erc-server-delayed-check-reconnect'.")
-
 (defun erc-server-prefer-check-reconnect (buffer)
   "Defer to another reconnector based on BUFFER's `erc-session-connector'.
 Prefer `erc-server-delayed-check-reconnect' if the connector is known to
 be \"check-aware\".  Otherwise, use `erc-server-delayed-reconnect'."
   (if (memq (buffer-local-value 'erc-session-connector buffer)
-            erc--server-delayed-check-connectors)
+            '(erc-open-tls-stream
+              erc-open-network-stream
+              erc-open-socks-tls-stream))
       (erc-server-delayed-check-reconnect buffer)
     (erc-server-delayed-reconnect buffer)))
 
diff --git a/test/lisp/erc/erc-scenarios-base-auto-recon.el 
b/test/lisp/erc/erc-scenarios-base-auto-recon.el
index d6a114147b3..adde30e6d47 100644
--- a/test/lisp/erc/erc-scenarios-base-auto-recon.el
+++ b/test/lisp/erc/erc-scenarios-base-auto-recon.el
@@ -100,6 +100,8 @@
       ((erc-server-flood-penalty 0.1)
        (erc-scenarios-common-dialog "base/reconnect")
        (erc-d-auto-pong nil)
+       (erc-d-tmpl-vars
+        `((cookie . ,(lambda (a) (funcall a :set (funcall a :match 1))))))
        (dumb-server (erc-d-run "localhost" t 'unexpected-disconnect))
        (port (process-contact dumb-server :service))
        (erc--server-reconnect-timeout-scale-function (lambda (_) 1))
@@ -128,7 +130,6 @@
     (ert-info ("Service restored")
       (setq dumb-server (erc-d-run "localhost" port
                                    'just-ping
-                                   'ping-pong
                                    'unexpected-disconnect))
       (with-current-buffer "FooNet"
         (funcall expect 30 "server is in debug mode")))
diff --git a/test/lisp/erc/resources/base/reconnect/ping-pong.eld 
b/test/lisp/erc/resources/base/reconnect/ping-pong.eld
deleted file mode 100644
index b3d36cf6cec..00000000000
--- a/test/lisp/erc/resources/base/reconnect/ping-pong.eld
+++ /dev/null
@@ -1,6 +0,0 @@
-;; -*- mode: lisp-data; -*-
-((ping 10 "PING ")
- (0 "PONG fake"))
-
-((eof 10 EOF))
-((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/reconnect/unexpected-disconnect.eld 
b/test/lisp/erc/resources/base/reconnect/unexpected-disconnect.eld
index 80903f94155..281239dfdaa 100644
--- a/test/lisp/erc/resources/base/reconnect/unexpected-disconnect.eld
+++ b/test/lisp/erc/resources/base/reconnect/unexpected-disconnect.eld
@@ -1,7 +1,8 @@
 ;; -*- mode: lisp-data; -*-
 
 ((~eof 60 EOF))
-((~ping 60 "PING"))
+((~ping 60 "PING " (group (+ (in "0-9"))))
+ (0 "PONG " cookie))
 
 ((nick 10 "NICK tester"))
 ((user 10 "USER user 0 * :tester")
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld 
b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld
deleted file mode 100644
index af216c80edc..00000000000
--- a/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld
+++ /dev/null
@@ -1,9 +0,0 @@
-;;; -*- mode: lisp-data -*-
-
-((pass 10.0 "PASS " (? ?:) "changeme"))
-((nick 0.2 "NICK tester"))
-
-((user 0.2 "USER user 0 * :" (group (+ alpha)) eos)
- (0 ":*status!znc@znc.in NOTICE " nick " :You have no networks configured."
-    " Use /znc AddNetwork <network> to add one.")
- (0 ":irc.znc.in 001 " nick " :Welcome " nick "!"))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]