Greetings.
This error appears, after Chawan downloads data from a given PubSub node.
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.108.Final.jar:4.1.108.Final]
at java.lang.Thread.run(Thread.java:840) [?:?]
2026.03.03 13:22:00.801 ERROR [socket_c2s_ssl-thread-4]: org.jivesoftware.openfire.nio.NettyConnection - Problem during connection close or cleanup
java.nio.channels.ClosedChannelException: null
at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1156) ~[netty-handler-4.1.108.Final.jar:4.1.108.Final]
This is the script which is being executed.
#!/usr/bin/env python3
# coding: utf-8
#
# Usage:
#
# printf "xmpp:pubsub.movim.eu?;node=berlin-xmpp-meetup" | python pubsub.py > berlin-xmpp-meetup.pubsub
#
import asyncio
import configparser
import datetime
import os
import select
import sys
from urllib.parse import urlparse
import xml.etree.ElementTree as ET
class Chawan:
def directives(cha_control, content=None, content_type=None, status_code=None) -> None:
if status_code:
sys.stdout.write(f"Status: {status_code}\n")
sys.stdout.write(f"Cha-Control: {cha_control}\n")
if content_type:
sys.stdout.write(f"Content-Type: {content_type}\n")
if content:
sys.stdout.write("\n")
sys.stdout.write(content)
sys.stdout.write("\n")
sys.stdout.flush()
sys.exit()
try:
from slixmpp import ClientXMPP
from slixmpp.exceptions import IqError, IqTimeout
from slixmpp.stanza.iq import Iq
#from slixmpp.xmlstream import ET
except Exception as e:
cha_control = f"ConnectionError InternalError {str(e)}"
content = content_type = status_code = None
Chawan.directives(cha_control, content, content_type, status_code)
class Xmpp:
async def pubsub(
client_xmpp: ClientXMPP, jid_bare: str, node_name=None, item_id=None
) -> dict:
result = {}
iq = None
try:
if jid_bare and node_name and item_id:
iq = await client_xmpp.plugin["xep_0060"].get_item(
jid_bare, node_name, item_id, timeout=5)
elif jid_bare and node_name:
iq = await client_xmpp.plugin["xep_0060"].get_items(
jid_bare, node_name, timeout=15)
elif jid_bare:
iq = await client_xmpp.plugin["xep_0060"].get_nodes(
jid_bare, timeout=10)
except (IqError, IqTimeout) as e:
error_condition = e.iq["error"]["condition"]
error_text = e.iq["error"]["text"]
if iq:
if "pubsub" in iq:
#if "items" in iq["pubsub"] and "item" in iq["pubsub"]["items"]:
if iq["pubsub"]["items"]["item"]["payload"] is not None:
result = {"content" : str(iq["pubsub"]),
"message" : "Success",
"error" : False}
else:
# This is not an error. It is a state of event of an empty node.
result = {"content" : None,
"message" : "PubSub node appears to be empty",
"error" : True}
elif "error" in iq:
result = {"content" : None,
"message" : f"{error_condition}: {error_text}",
"error" : True}
else:
result = {"content" : None,
"message" : f"Unknown error: {str(iq)}",
"error" : True}
else:
result = {"content" : None,
"message" : "Unknown error: Stanza IQ is empty",
"error" : True}
return result
if __name__ == "__main__":
directory_data = (
os.environ.get("CHA_DATA_DIR") or
os.path.join(os.environ.get("HOME"), ".local/share/chawan"))
credentials = os.path.join(directory_data, "credentials.ini")
config = configparser.ConfigParser()
config.read(credentials)
if ("xmpp" in config and
"address" in config["xmpp"] and
"password" in config["xmpp"]):
address = config["xmpp"]["address"]
password = config["xmpp"]["password"]
stdin_input = sys.stdin.read()
if stdin_input:
uri = stdin_input
else:
uri_scheme = os.environ.get("MAPPED_URI_SCHEME")
uri_path = os.environ.get("MAPPED_URI_PATH")
uri_query = os.environ.get("MAPPED_URI_QUERY")
uri = f"{uri_scheme}:{uri_path}?{uri_query}"
fragmented_uri = urlparse(uri)
if fragmented_uri.scheme == "xmpp":
jid_bare = fragmented_uri.path
item_id = node_name = None
for parameter in fragmented_uri.query.split(";"):
if parameter.startswith("node="):
node_name = parameter[5:]
if parameter.startswith("item="):
item_id = parameter[5:]
if jid_bare or jid_bare and node_name:
client_xmpp = ClientXMPP(address, password)
client_xmpp.register_plugin("xep_0060")
#client_xmpp.register_plugin("xep_0199")
#client_xmpp.connect()
# ERROR:slixmpp.features.feature_mechanisms.mechanisms:No appropriate login method.
loop = asyncio.get_event_loop()
#rtt = loop.run_until_complete(client_xmpp.plugin["xep_0199"].ping())
#if rtt:
try:
client_xmpp.connect()
#result = asyncio.run(
# Xmpp.pubsub(client_xmpp, jid_bare, node_name, item_id))
result = loop.run_until_complete(
Xmpp.pubsub(client_xmpp, jid_bare, node_name, item_id))
client_xmpp.disconnect(
ignore_send_queue=False,
reason="Chawan: Receiving PubSub data was completed.",
wait=2.0)
# TODO if no items in result node (an empty node)
if result["error"]:
message = result["message"]
cha_control = f"ConnectionError ConnectionRefused {message}."
content = content_type = status_code = None
else:
"""
xml = ET.fromstring(result["content"])
namespaces = {
"atom" : "http://www.w3.org/2005/Atom",
"pubsub" : "http://jabber.org/protocol/pubsub",
"xhtml" : "http://www.w3.org/1999/xhtml"}
for namespace in namespaces:
ET.register_namespace(
namespace, namespaces[namespace])
ET.indent(xml, space=" ", level=0)
content = ET.tostring(xml, encoding="unicode")
"""
content = result["content"]
cha_control = "ControlDone"
content_type = "application/pubsub+xml"
status_code = "200"
except Exception as e:
message = f"Check whether credentials or XMPP URI are valid; {str(e)}"
cha_control = f"ConnectionError ConnectionRefused {message}."
content = content_type = status_code = None
else:
message = f"Jabber ID or Node Name appear to be missing: {uri}"
cha_control = f"ConnectionError InvalidURL {message}."
content = content_type = status_code = None
else:
message = f"Invalid XMPP PubSub Query URI: {uri}"
cha_control = f"ConnectionError InvalidURL {message}."
content = content_type = status_code = None
else:
message = f"XMPP credentials are missing {credentials}"
cha_control = f"ConnectionError InternalError {message}."
content = content_type = status_code = None
Chawan.directives(cha_control, content, content_type, status_code)
Command: printf “xmpp:pubsub.movim.eu?;node=berlin-xmpp-meetup” | python pubsub.py.