能否自定义ejabberd中<presence>的<show/>元素状态选项?
自定义ejabberd中的
<presence><show/>元素:可行方案与注意事项 当然可以自定义ejabberd里的<show/>元素值,但要兼顾XMPP协议的兼容性和服务器的扩展逻辑,下面是具体的实现思路和步骤:
一、核心思路:覆盖ejabberd的默认presence验证
ejabberd默认会遵循RFC3921的规则校验<show/>的值,所以我们需要通过自定义模块来拦截并修改presence数据包的处理逻辑,允许我们需要的自定义值,同时移除不需要的chat状态。
1. 编写自定义ejabberd模块
你可以写一个Erlang模块,通过ejabberd的hook机制拦截presence stanza,校验并修改<show/>元素的值。以下是一个简化的示例:
-module(custom_presence_show). -behaviour(ejabberd_gen_mod). -export([start/2, stop/1, filter_packet/1]). start(_Host, _Opts) -> % 注册filter_packet hook,拦截所有数据包 ejabberd_hooks:add(filter_packet, global, ?MODULE, filter_packet, 50), ok. stop(_Host) -> ejabberd_hooks:delete(filter_packet, global, ?MODULE, filter_packet, 50), ok. filter_packet({From, To, XML} = Packet) -> case XML of #xmlel{name = <<"presence">>, children = Children} -> NewChildren = lists:map(fun (#xmlel{name = <<"show">>, children = [ShowText]}) -> % 定义允许的状态值:移除chat,添加working、vacation AllowedShows = [<<"away">>, <<"dnd">>, <<"xa">>, <<"working">>, <<"vacation">>], ShowBin = xml:get_tag_cdata(ShowText), case lists:member(ShowBin, AllowedShows) of true -> #xmlel{name = <<"show">>, children = [ShowText]}; false -> % 对于不允许的值,可以替换为默认状态,或者直接丢弃该元素 #xmlel{name = <<"show">>, children = [#xmlcdata{content = <<"away">>}]} end; (Child) -> Child end, Children), {From, To, #xmlel{name = <<"presence">>, children = NewChildren}}; _ -> Packet end.
2. 部署并启用模块
- 将上述代码编译成
.beam文件,放到ejabberd的模块目录(通常是/usr/lib/ejabberd/ebin/或自定义路径)。 - 在ejabberd的配置文件
ejabberd.yml中添加模块启用配置:
modules: # ...其他模块... custom_presence_show: {}
- 重启ejabberd服务使配置生效。
二、客户端适配要点
自定义的<show/>值需要客户端支持才能正确显示:
- 如果使用的是开源客户端(比如Conversations、Pidgin),可能需要修改客户端代码,添加对自定义状态值的UI映射(比如对应图标、显示文本)。
- 如果是自研客户端,可以直接在状态选择器中加入自定义选项,并将选中值作为
<show/>的内容发送给服务器。
三、兼容性与最佳实践
- 跨客户端兼容性:部分标准XMPP客户端可能会忽略不认识的
<show/>值,或者将其显示为默认的"away"状态,所以如果需要广泛兼容,建议考虑通过XMPP扩展(比如自定义IQ或扩展字段)来实现额外状态,而非直接修改标准的<show/>元素。 - 服务器状态存储:如果需要服务器端持久化或广播这些自定义状态,确保ejabberd的presence存储逻辑能正确处理这些值(默认情况下,ejabberd会存储完整的presence stanza,所以只要你的模块允许通过,就能正常存储)。
- 协议规范考量:虽然RFC3921定义了固定的
<show/>值,但XMPP的设计允许扩展,只要你的服务和客户端能协同工作,自定义是完全可行的。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

