From b1b80031744fa1635478e28fb513c2de29e5ee1f Mon Sep 17 00:00:00 2001 From: Stefan Strigler Date: Wed, 28 May 2025 11:15:29 +0200 Subject: [PATCH 1/3] mod_pubsub_serverinfo: fix fetch_public_hosts (body must be binary) --- mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl b/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl index 21c7047f..e665893a 100644 --- a/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl +++ b/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl @@ -87,7 +87,7 @@ init_monitors(Host) -> -spec fetch_public_hosts() -> list(). fetch_public_hosts() -> try - {ok, {{_, 200, _}, _Headers, Body}} = httpc:request(?PUBLIC_HOSTS_URL), + {ok, {{_, 200, _}, _Headers, Body}} = httpc:request(get, {?PUBLIC_HOSTS_URL, []}, [{timeout, 1000}], [{body_format, binary}]), case misc:json_decode(Body) of PublicHosts when is_list(PublicHosts) -> PublicHosts; Other -> From 2393861804677197af8e32168ccfbc9fc90fb677 Mon Sep 17 00:00:00 2001 From: Stefan Strigler Date: Wed, 28 May 2025 11:34:37 +0200 Subject: [PATCH 2/3] mod_pubsub_serverinfo: add option `pubsub_host` Also when choosing a pubsub host were now acknowledgin mod_pubsub's `hosts` option, especially since `host` is deprecated. --- mod_pubsub_serverinfo/README.md | 27 ++++++-- .../src/mod_pubsub_serverinfo.erl | 65 +++++++++++++++---- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/mod_pubsub_serverinfo/README.md b/mod_pubsub_serverinfo/README.md index 684f226d..4b6eaf60 100644 --- a/mod_pubsub_serverinfo/README.md +++ b/mod_pubsub_serverinfo/README.md @@ -2,6 +2,7 @@ mod_pubsub_serverinfo - Exposes server information over Pub/Sub ============================================================== * Author: Guus der Kinderen +* Author: Stefan Strigler Description ----------- @@ -9,8 +10,17 @@ Description Announces support for the ProtoXEP PubSub Server Information, by adding its Service Discovery feature. -Future versions of this plugin are expected to publish data describing -the local XMPP domain(s). +Active S2S connections are published to a local pubsub node as advertised by +Service Discovery. Only those connections that support this feature as well are +exposed with their domain names, otherwise they are shown as anonymous nodes. At +startup a list of well known public servers is being fetched. Those are not +shown as anonymous even if they don't support this feature. + +Currently the name of the node is hardcoded as "serverinfo". The local service +to be used can be configured as `pubsub_host`. Otherwise a good guess is taken. + +This module has a hard dependency on `mod_pubsub` for this reason. Also +`mod_disco` must be configured for this feature to work. > [!NOTE] > The module only shows S2S connections established while the module is running: @@ -20,9 +30,12 @@ the local XMPP domain(s). Configuration ------------- -This module does not have any configurable settings for now. +Configurable options for `mod_pubsub_serverinfo`: + +- `pubsub_host` (default: undefined) -> [!NOTE] -> As of now your pubsub component must be reachable at `pubsub.` (the -> default), otherwise this module would advertise the wrong address. -> See: https://github.com/processone/ejabberd-contrib/issues/343 + This option specifies which pubsub host to use to advertise S2S connections. + This must be a vhost local to this service and handled by `mod_pubsub`. This + is only needed if your configuration has more than one vhost in mod_pubsub's + `hosts` option. If there's more than one and this option is not given, we just + pick the first one. diff --git a/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl b/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl index e665893a..f5bb94ff 100644 --- a/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl +++ b/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl @@ -33,7 +33,7 @@ -include_lib("xmpp/include/xmpp.hrl"). %% gen_mod callbacks. --export([start/2, stop/1, depends/2, mod_options/1, get_local_features/5, mod_doc/0]). +-export([start/2, stop/1, depends/2, mod_options/1, mod_opt_type/1, get_local_features/5, mod_doc/0]). -export([init/1, handle_cast/2, handle_call/3, handle_info/2, terminate/2]). -export([in_auth_result/3, out_auth_result/2, get_info/5]). @@ -43,12 +43,17 @@ -record(state, {host, pubsub_host, node, monitors = #{}, timer = undefined, public_hosts = []}). start(Host, Opts) -> - xmpp:register_codec(pubsub_serverinfo_codec), - ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 50), - ejabberd_hooks:add(disco_info, Host, ?MODULE, get_info, 50), - ejabberd_hooks:add(s2s_out_auth_result, Host, ?MODULE, out_auth_result, 50), - ejabberd_hooks:add(s2s_in_auth_result, Host, ?MODULE, in_auth_result, 50), - gen_mod:start_child(?MODULE, Host, Opts). + case pubsub_host(Host, Opts) of + {error, _Reason} = Error -> + Error; + PubsubHost -> + xmpp:register_codec(pubsub_serverinfo_codec), + ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 50), + ejabberd_hooks:add(disco_info, Host, ?MODULE, get_info, 50), + ejabberd_hooks:add(s2s_out_auth_result, Host, ?MODULE, out_auth_result, 50), + ejabberd_hooks:add(s2s_in_auth_result, Host, ?MODULE, in_auth_result, 50), + gen_mod:start_child(?MODULE, Host, PubsubHost) + end. stop(Host) -> ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 50), @@ -57,11 +62,10 @@ stop(Host) -> ejabberd_hooks:delete(s2s_in_auth_result, Host, ?MODULE, in_auth_result, 50), gen_mod:stop_child(?MODULE, Host). -init([Host, _Opts]) -> +init([Host, PubsubHost]) -> TRef = timer:send_interval(timer:minutes(5), self(), update_pubsub), Monitors = init_monitors(Host), PublicHosts = fetch_public_hosts(), - PubsubHost = gen_mod:get_module_opt(Host, mod_pubsub, host), State = #state{host = Host, pubsub_host = PubsubHost, node = <<"serverinfo">>, @@ -171,7 +175,10 @@ depends(_Host, _Opts) -> [{mod_pubsub, hard}]. mod_options(_Host) -> - []. + [{pubsub_host, undefined}]. + +mod_opt_type(pubsub_host) -> + econf:either(undefined, econf:host()). mod_doc() -> #{}. @@ -251,7 +258,7 @@ get_local_features(Acc, _From, _To, _Node, _Lang) -> get_info(Acc, Host, Mod, Node, Lang) when (Mod == undefined orelse Mod == mod_disco), Node == <<"">> -> case mod_disco:get_info(Acc, Host, Mod, Node, Lang) of [#xdata{fields = Fields} = XD | Rest] -> - PubsubHost = gen_mod:get_module_opt(Host, mod_pubsub, host), + PubsubHost = pubsub_host(Host), NodeField = #xdata_field{var = <<"serverinfo-pubsub-node">>, values = [<<"xmpp:", PubsubHost/binary, "?;node=serverinfo">>]}, {stop, [XD#xdata{fields = Fields ++ [NodeField]} | Rest]}; @@ -259,7 +266,7 @@ get_info(Acc, Host, Mod, Node, Lang) when (Mod == undefined orelse Mod == mod_di Acc end; get_info(Acc, Host, Mod, Node, _Lang) when Node == <<"">>, is_atom(Mod) -> - PubsubHost = gen_mod:get_module_opt(Host, mod_pubsub, host), + PubsubHost = pubsub_host(Host), [#xdata{type = result, fields = [ #xdata_field{type = hidden, @@ -269,3 +276,37 @@ get_info(Acc, Host, Mod, Node, _Lang) when Node == <<"">>, is_atom(Mod) -> values = [<<"xmpp:", PubsubHost/binary, "?;node=serverinfo">>]}]} | Acc]; get_info(Acc, _Host, _Mod, _Node, _Lang) -> Acc. + +pubsub_host(Host) -> + case pubsub_host(Host, gen_mod:get_module_opts(Host, mod_pubsub)) of + {error, _Reason} = Error -> + throw(Error); + PubsubHost -> + PubsubHost + end. + +pubsub_host(Host, Opts) -> + case gen_mod:get_opt(pubsub_host, Opts) of + undefined -> + PubsubHost = hd(get_mod_pubsub_hosts(Host)), + ?INFO_MSG("No pubsub_host in configuration for ~p, choosing ~s", [?MODULE, PubsubHost]), + PubsubHost; + PubsubHost -> + case check_pubsub_host_exists(Host, PubsubHost) of + true -> + PubsubHost; + false -> + {error, {pubsub_host_does_not_exist, PubsubHost}} + end + end. + +check_pubsub_host_exists(Host, PubsubHost) -> + lists:member(PubsubHost, get_mod_pubsub_hosts(Host)). + +get_mod_pubsub_hosts(Host) -> + case gen_mod:get_module_opt(Host, mod_pubsub, hosts) of + [] -> + [gen_mod:get_module_opt(Host, mod_pubsub, host)]; + PubsubHosts -> + PubsubHosts + end. From 0fc150a4d439cbca643359f9d7655fdc3210bd1a Mon Sep 17 00:00:00 2001 From: Stefan Strigler Date: Wed, 28 May 2025 11:53:39 +0200 Subject: [PATCH 3/3] mod_pubsub_serverinfo: change author --- mod_pubsub_serverinfo/README.md | 3 ++- mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mod_pubsub_serverinfo/README.md b/mod_pubsub_serverinfo/README.md index 4b6eaf60..ee82b21f 100644 --- a/mod_pubsub_serverinfo/README.md +++ b/mod_pubsub_serverinfo/README.md @@ -1,9 +1,10 @@ mod_pubsub_serverinfo - Exposes server information over Pub/Sub ============================================================== -* Author: Guus der Kinderen * Author: Stefan Strigler +Initially created by Guus der Kinderen. + Description ----------- diff --git a/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl b/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl index f5bb94ff..a97637fa 100644 --- a/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl +++ b/mod_pubsub_serverinfo/src/mod_pubsub_serverinfo.erl @@ -1,11 +1,11 @@ %%%---------------------------------------------------------------------- %%% File : mod_pubsub_serverinfo.erl -%%% Author : Guus der Kinderen +%%% Author : Stefan Strigler %%% Purpose : Exposes server information over Pub/Sub %%% Created : 26 Dec 2023 by Guus der Kinderen %%% %%% -%%% ejabberd, Copyright (C) 2023 ProcessOne +%%% ejabberd, Copyright (C) 2023 - 2025 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -24,7 +24,7 @@ %%%---------------------------------------------------------------------- -module(mod_pubsub_serverinfo). --author('guus.der.kinderen@gmail.com'). +-author('stefan@strigler.de'). -behaviour(gen_mod). -behaviour(gen_server).