Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

module: added support for xep-0313 #241

Merged
merged 1 commit into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,11 @@ Once up and running, don't forget to [register one or more users](#creating-jack
- [XEP-0030: Service Discovery](https://xmpp.org/extensions/xep-0030.html) *2.5rc3*
- [XEP-0049: Private XML Storage](https://xmpp.org/extensions/xep-0049.html) *1.2*
- [XEP-0054: vcard-temp](https://xmpp.org/extensions/xep-0054.html) *1.2*
- [XEP-0059: Result Set Management](https://xmpp.org/extensions/xep-0059.html) *1.0*
- [XEP-0092: Software Version](https://xmpp.org/extensions/xep-0092.html) *1.1*
- [XEP-0114: Jabber Component Protocol](https://xmpp.org/extensions/xep-0114.html) *1.6*
- [XEP-0115: Entity Capabilities](https://xmpp.org/extensions/xep-0115.html) *1.5.2*
- [XEP-0115: Entity Capabilities](https://xmpp.org/extensions/xep-0115.html) *1.5.2*
- [XEP-0122: Data Forms Validation](https://xmpp.org/extensions/xep-0122.html) *1.0.2*
- [XEP-0138: Stream Compression](https://xmpp.org/extensions/xep-0138.html) *2.0*
- [XEP-0160: Best Practices for Handling Offline Messages](https://xmpp.org/extensions/xep-0160.html) *1.0.1*
- [XEP-0190: Best Practice for Closing Idle Streams](https://xmpp.org/extensions/xep-0190.html) *1.1*
Expand All @@ -214,6 +216,8 @@ Once up and running, don't forget to [register one or more users](#creating-jack
- [XEP-0220: Server Dialback](https://xmpp.org/extensions/xep-0220.html) *1.1.1*
- [XEP-0237: Roster Versioning](https://xmpp.org/extensions/xep-0237.html) *1.3*
- [XEP-0280: Message Carbons](https://xmpp.org/extensions/xep-0280.html) *0.13.3*
- [XEP-0297: Stanza Forwarding](https://xmpp.org/extensions/xep-0297.html) *1.0*
- [XEP-0313: Message Archive Management](https://xmpp.org/extensions/xep-0313.html) *1.0.1*
- [XEP-0368: SRV records for XMPP over TLS](https://xmpp.org/extensions/xep-0368.html) *1.1.0*

## Join and Contribute
Expand Down
5 changes: 5 additions & 0 deletions config/example.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ modules:
# - ping # XEP-0199: XMPP Ping
# - time # XEP-0202: Entity Time
# - carbons # XEP-0280: Message Carbons
# - mam # XEP-0313: Message Archive Management
#
# version:
# show_os: true
Expand All @@ -140,6 +141,10 @@ modules:
# interval: 3m
# send_pings: true
# timeout_action: kill
#
# mam:
# queue_size: 1500
#

components:
secret: a-super-secret-key
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ require (
github.com/google/uuid v1.1.2
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/jackal-xmpp/runqueue/v2 v2.0.0
github.com/jackal-xmpp/stravaganza v1.2.3
github.com/jackal-xmpp/stravaganza v1.2.4
github.com/kkyr/fig v0.2.0
github.com/lib/pq v1.8.0
github.com/mattn/go-sqlite3 v1.14.5 // indirect
github.com/prometheus/client_golang v1.11.0
github.com/samber/lo v1.25.0
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.1
Expand Down Expand Up @@ -61,6 +62,7 @@ require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.17.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
golang.org/x/text v0.3.7 // indirect
Expand Down
12 changes: 9 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
github.com/jackal-xmpp/runqueue/v2 v2.0.0 h1:QfvOfL6zF5yK1LN5TKabpj+VBuELMwtR8Xpkz0CrjoI=
github.com/jackal-xmpp/runqueue/v2 v2.0.0/go.mod h1:tXZARVqBMGeV8BTc/qDPg0qXILTUWmER7wlYbN9Xcac=
github.com/jackal-xmpp/stravaganza v1.2.3 h1:fxxyvtkj94CHYfooy7YsFRue7jFtJaMg3BozfWlzSOY=
github.com/jackal-xmpp/stravaganza v1.2.3/go.mod h1:oesgQpMM0I5gnJM80NsEfSspzDDCArQex+oA0/swCWU=
github.com/jackal-xmpp/stravaganza v1.2.4 h1:xz3L2lNEPezOn43az4W4omK1at9tSuR4BDaWOSKo6aE=
github.com/jackal-xmpp/stravaganza v1.2.4/go.mod h1:oesgQpMM0I5gnJM80NsEfSspzDDCArQex+oA0/swCWU=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
Expand Down Expand Up @@ -306,6 +306,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
Expand Down Expand Up @@ -363,6 +364,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.25.0 h1:H8F6cB0RotRdgcRCivTByAQePaYhGMdOTJIj2QFS2I0=
github.com/samber/lo v1.25.0/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
Expand Down Expand Up @@ -397,6 +400,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
Expand Down Expand Up @@ -450,6 +454,8 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down Expand Up @@ -642,8 +648,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
Expand Down
22 changes: 22 additions & 0 deletions helm/sql/postgres.up.psql
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,25 @@ CREATE TABLE IF NOT EXISTS vcards (
);

SELECT enable_updated_at('vcards');

-- archives

CREATE TABLE IF NOT EXISTS archives (
serial SERIAL PRIMARY KEY,
archive_id VARCHAR(1023),
id VARCHAR(255) NOT NULL,
"from" TEXT NOT NULL,
from_bare TEXT NOT NULL,
"to" TEXT NOT NULL,
to_bare TEXT NOT NULL,
message BYTEA NOT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS i_archives_archive_id ON archives(archive_id);
CREATE INDEX IF NOT EXISTS i_archives_id ON archives(id);
CREATE INDEX IF NOT EXISTS i_archives_to ON archives("to");
CREATE INDEX IF NOT EXISTS i_archives_to_bare ON archives(to_bare);
CREATE INDEX IF NOT EXISTS i_archives_from ON archives("from");
CREATE INDEX IF NOT EXISTS i_archives_from_bare ON archives(from_bare);
CREATE INDEX IF NOT EXISTS i_archives_created_at ON archives(created_at);
4 changes: 4 additions & 0 deletions helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ jackal:
- ping # XEP-0199: XMPP Ping
- time # XEP-0202: Entity Time
- carbons # XEP-0280: Message Carbons
- mam # XEP-0313: Message Archive Management

version:
show_os: true
Expand All @@ -138,6 +139,9 @@ jackal:
send_pings: true
timeout_action: kill

mam:
queue_size: 1500

components:
# listeners:
# - port: 5275
Expand Down
2 changes: 1 addition & 1 deletion pkg/admin/pb/users.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 46 additions & 36 deletions pkg/c2s/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,13 +404,13 @@ func (s *inC2S) connTimeout() {

func (s *inC2S) handleElement(ctx context.Context, elem stravaganza.Element) error {
// run received element hook
hInf := &hook.C2SStreamInfo{
hi := &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: elem,
}
halted, err := s.runHook(ctx, hook.C2SStreamElementReceived, hInf)
halted, err := s.runHook(ctx, hook.C2SStreamElementReceived, hi)
if halted {
return nil
}
Expand All @@ -421,15 +421,15 @@ func (s *inC2S) handleElement(ctx context.Context, elem stravaganza.Element) err
t0 := time.Now()
switch s.getState() {
case inConnecting:
err = s.handleConnecting(ctx, hInf.Element)
err = s.handleConnecting(ctx, hi.Element)
case inConnected:
err = s.handleConnected(ctx, hInf.Element)
err = s.handleConnected(ctx, hi.Element)
case inAuthenticating:
err = s.handleAuthenticating(ctx, hInf.Element)
err = s.handleAuthenticating(ctx, hi.Element)
case inAuthenticated:
err = s.handleAuthenticated(ctx, hInf.Element)
err = s.handleAuthenticated(ctx, hi.Element)
case inBinded:
err = s.handleBinded(ctx, hInf.Element)
err = s.handleBinded(ctx, hi.Element)
}
reportIncomingRequest(
elem.Name(),
Expand Down Expand Up @@ -553,15 +553,18 @@ func (s *inC2S) processStanza(ctx context.Context, stanza stravaganza.Stanza) er

func (s *inC2S) processIQ(ctx context.Context, iq *stravaganza.IQ) error {
// run iq received hook
_, err := s.runHook(ctx, hook.C2SStreamIQReceived, &hook.C2SStreamInfo{
hi := &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: iq,
})
}
_, err := s.runHook(ctx, hook.C2SStreamIQReceived, hi)
if err != nil {
return err
}
iq = hi.Element.(*stravaganza.IQ)

if iq.IsSet() && iq.ChildNamespace("session", sessionNamespace) != nil {
if !s.flags.isSessionStarted() {
s.flags.setSessionStarted()
Expand All @@ -576,24 +579,24 @@ func (s *inC2S) processIQ(ctx context.Context, iq *stravaganza.IQ) error {
return s.mods.ProcessIQ(ctx, iq)
}
// run will route iq hook
hInf := &hook.C2SStreamInfo{
hi = &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: iq,
}
halted, err := s.runHook(ctx, hook.C2SStreamWillRouteElement, hInf)
halted, err := s.runHook(ctx, hook.C2SStreamWillRouteElement, hi)
if halted {
return nil
}
if err != nil {
return err
}
outIQ, ok := hInf.Element.(*stravaganza.IQ)
iq, ok := hi.Element.(*stravaganza.IQ)
if !ok {
return nil
}
targets, err := s.router.Route(ctx, outIQ)
targets, err := s.router.Route(ctx, iq)
switch err {
case router.ErrResourceNotFound:
return s.sendElement(ctx, stanzaerror.E(stanzaerror.ServiceUnavailable, iq).Element())
Expand All @@ -604,8 +607,8 @@ func (s *inC2S) processIQ(ctx context.Context, iq *stravaganza.IQ) error {
case router.ErrRemoteServerTimeout:
return s.sendElement(ctx, stanzaerror.E(stanzaerror.RemoteServerTimeout, iq).Element())

case nil:
_, err := s.runHook(ctx, hook.C2SStreamIQRouted, &hook.C2SStreamInfo{
case nil, router.ErrUserNotAvailable:
_, err = s.runHook(ctx, hook.C2SStreamIQRouted, &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Expand All @@ -619,38 +622,40 @@ func (s *inC2S) processIQ(ctx context.Context, iq *stravaganza.IQ) error {

func (s *inC2S) processPresence(ctx context.Context, presence *stravaganza.Presence) error {
// run presence received hook
_, err := s.runHook(ctx, hook.C2SStreamPresenceReceived, &hook.C2SStreamInfo{
hi := &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: presence,
})
}
_, err := s.runHook(ctx, hook.C2SStreamPresenceReceived, hi)
if err != nil {
return err
}
presence = hi.Element.(*stravaganza.Presence)

if presence.ToJID().IsFullWithUser() {
// run will route presence hook
hInf := &hook.C2SStreamInfo{
hi = &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: presence,
}
halted, err := s.runHook(ctx, hook.C2SStreamWillRouteElement, hInf)
halted, err := s.runHook(ctx, hook.C2SStreamWillRouteElement, hi)
if halted {
return nil
}
if err != nil {
return err
}
outPr, ok := hInf.Element.(*stravaganza.Presence)
presence, ok := hi.Element.(*stravaganza.Presence)
if !ok {
return nil
}
targets, err := s.router.Route(ctx, outPr)
targets, err := s.router.Route(ctx, presence)
switch err {
case nil:
case nil, router.ErrUserNotAvailable:
_, err = s.runHook(ctx, hook.C2SStreamPresenceRouted, &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Expand All @@ -672,37 +677,38 @@ func (s *inC2S) processPresence(ctx context.Context, presence *stravaganza.Prese

func (s *inC2S) processMessage(ctx context.Context, message *stravaganza.Message) error {
// run message received hook
_, err := s.runHook(ctx, hook.C2SStreamMessageReceived, &hook.C2SStreamInfo{
hi := &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: message,
})
}
_, err := s.runHook(ctx, hook.C2SStreamMessageReceived, hi)
if err != nil {
return err
}
msg := message
msg := hi.Element.(*stravaganza.Message)

sendMsg:
// run will route Message hook
hInf := &hook.C2SStreamInfo{
// run will route message hook
hi = &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Element: msg,
}
halted, err := s.runHook(ctx, hook.C2SStreamWillRouteElement, hInf)
halted, err := s.runHook(ctx, hook.C2SStreamWillRouteElement, hi)
if halted {
return nil
}
if err != nil {
return err
}
outMsg, ok := hInf.Element.(*stravaganza.Message)
msg, ok := hi.Element.(*stravaganza.Message)
if !ok {
return nil
}
targets, err := s.router.Route(ctx, outMsg)
targets, err := s.router.Route(ctx, msg)
switch err {
case router.ErrResourceNotFound:
// treat the stanza as if it were addressed to <node@domain>
Expand All @@ -721,18 +727,21 @@ sendMsg:
case router.ErrRemoteServerTimeout:
return s.sendElement(ctx, stanzaerror.E(stanzaerror.RemoteServerTimeout, message).Element())

case router.ErrUserNotAvailable:
return s.sendElement(ctx, stanzaerror.E(stanzaerror.ServiceUnavailable, message).Element())

case nil:
_, err = s.runHook(ctx, hook.C2SStreamMessageRouted, &hook.C2SStreamInfo{
case nil, router.ErrUserNotAvailable:
halted, hErr := s.runHook(ctx, hook.C2SStreamMessageRouted, &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
Targets: targets,
Element: msg,
})
return err
if halted {
return nil
}
if errors.Is(err, router.ErrUserNotAvailable) {
return s.sendElement(ctx, stanzaerror.E(stanzaerror.ServiceUnavailable, message).Element())
}
return hErr

default:
return err
Expand Down Expand Up @@ -1108,6 +1117,7 @@ func (s *inC2S) close(ctx context.Context, disconnectErr error) error {
halted, err := s.runHook(ctx, hook.C2SStreamDisconnected, &hook.C2SStreamInfo{
ID: s.ID().String(),
JID: s.JID(),
Presence: s.Presence(),
DisconnectError: disconnectErr,
})
if halted {
Expand Down
Loading