From 23c74d828c43defc4c8dd861520ba0c40138e805 Mon Sep 17 00:00:00 2001
From: "Schimon Jehudah, Adv." <sjehuda@yandex.com>
Date: Mon, 10 Mar 2025 12:05:56 +0200
Subject: [PATCH] Utilize an active action (e.g. ping) to determine
 connectivity.

---
 blasta/http/instance.py | 11 +++++++----
 blasta/xmpp/instance.py |  9 ++++++++-
 blasta/xmpp/ping.py     | 17 +++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)
 create mode 100644 blasta/xmpp/ping.py

diff --git a/blasta/http/instance.py b/blasta/http/instance.py
index 954282a..3d5a0f8 100644
--- a/blasta/http/instance.py
+++ b/blasta/http/instance.py
@@ -13,6 +13,7 @@ from blasta.utilities.syndication import UtilitiesSyndication
 from blasta.xmpp.form import DataForm
 from blasta.xmpp.instance import XmppInstance
 from blasta.xmpp.iq import XmppIq
+from blasta.xmpp.ping import XmppPing
 from blasta.xmpp.pubsub import XmppPubsub
 from fastapi import Cookie, FastAPI, File, Form, HTTPException, Request, Response, UploadFile
 from fastapi.middleware.cors import CORSMiddleware
@@ -1283,11 +1284,13 @@ class HttpInstance:
                 session_key = str(random.random())
                 request.app.state.session_key = session_key
                 accounts[jabber_id] = XmppInstance(jabber_id + '/blasta', password)
-                if accounts[jabber_id].is_connected:
+                xmpp_instance = accounts[jabber_id]
+                rtt = await XmppPing.to_self(xmpp_instance)
+                if rtt or xmpp_instance.is_connected:
                     sessions[jabber_id] = session_key
                 else:
                     del accounts[jabber_id]
-                    jabber_id = None
+                    jabber_id = xmpp_instance = None
                 
                 # Check if the user and password are present and valid
                 # If not valid, return "Could not connect to JID"
@@ -1300,8 +1303,8 @@ class HttpInstance:
             await asyncio.sleep(5)
             #if jabber_id in accounts and accounts[jabber_id].connection_accepted:
 
-            if jabber_id in accounts:
-                xmpp_instance = accounts[jabber_id]
+            if xmpp_instance:
+                #xmpp_instance = accounts[jabber_id]
                 #await xmpp_instance.plugin['xep_0060'].delete_node(jabber_id, node_public_id)
 
                 for node_properties in nodes:
diff --git a/blasta/xmpp/instance.py b/blasta/xmpp/instance.py
index c41b337..63d0471 100644
--- a/blasta/xmpp/instance.py
+++ b/blasta/xmpp/instance.py
@@ -15,6 +15,7 @@ class XmppInstance(ClientXMPP):
         super().__init__(jid, password)
         self.add_event_handler("connection_failed", self.on_connection_failed)
         self.add_event_handler("failed_auth", self.on_failed_auth)
+        self.add_event_handler("got_offline", self.on_got_offline)
         self.add_event_handler("session_start", self.on_session_start)
         self.register_plugin('xep_0004') # XEP-0004: Data Forms
         self.register_plugin('xep_0030') # XEP-0030: Service Discovery
@@ -22,9 +23,9 @@ class XmppInstance(ClientXMPP):
         self.register_plugin('xep_0060') # XEP-0060: Publish-Subscribe
         self.register_plugin('xep_0078') # XEP-0078: Non-SASL Authentication
         self.register_plugin('xep_0163') # XEP-0163: Personal Eventing Protocol
+        self.register_plugin('xep_0199') # XEP-0199: XMPP Ping
         self.register_plugin('xep_0223') # XEP-0223: Persistent Storage of Private Data via PubSub
         self.connect()
-        self.is_connected = False
 
     def on_connection_failed(self, event):
         function_name = sys._getframe().f_code.co_name
@@ -38,6 +39,12 @@ class XmppInstance(ClientXMPP):
         self.is_connected = False
         logger.debug(f'{function_name},{event},Finish')
 
+    def on_got_offline(self, event):
+        function_name = sys._getframe().f_code.co_name
+        logger.debug(f'{function_name},{event},Start')
+        self.is_connected = False
+        logger.debug(f'{function_name},{event},Finish')
+
     def on_session_start(self, event):
         function_name = sys._getframe().f_code.co_name
         logger.debug(f'{function_name},{event},Start')
diff --git a/blasta/xmpp/ping.py b/blasta/xmpp/ping.py
new file mode 100644
index 0000000..e9db484
--- /dev/null
+++ b/blasta/xmpp/ping.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from blasta.utilities.logger import UtilitiesLogger
+#from slixmpp.exceptions import IqError, IqTimeout
+import sys
+
+logger = UtilitiesLogger(__name__)
+
+class XmppPing:
+
+    async def to_self(xmpp_instance):
+        function_name = sys._getframe().f_code.co_name
+        logger.debug(f'{function_name},,Start')
+        rtt = await xmpp_instance.plugin['xep_0199'].ping()
+        logger.debug(f'{function_name},,Finish')
+        return rtt