xmpp works with components (distribute Encoding hangs) - dirty without Webserver, and nice tokens

This commit is contained in:
Geno 2021-09-12 00:31:03 +02:00
parent 950a147042
commit be6e6c4154
4 changed files with 69 additions and 81 deletions

View File

@ -4,9 +4,9 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/xml" "encoding/xml"
"io"
"errors" "errors"
"fmt" "fmt"
"io"
"strings" "strings"
"github.com/bdlm/log" "github.com/bdlm/log"
@ -26,7 +26,7 @@ type XMPPService struct {
Password string Password string
Gateway string Gateway string
dbus *distributor.DBus dbus *distributor.DBus
session *xmpp.Session session *xmpp.Session
} }
func (s *XMPPService) Run(dbus *distributor.DBus) error { func (s *XMPPService) Run(dbus *distributor.DBus) error {
@ -60,31 +60,12 @@ func (s *XMPPService) Run(dbus *distributor.DBus) error {
if err != nil { if err != nil {
return err return err
} }
// Send subscripe to ask for allowing sending IQ (Register/Unregister)
err = s.session.Send(context.TODO(), stanza.Presence{
Type: stanza.SubscribePresence,
To: jid.MustParse(s.Gateway),
}.Wrap(nil))
if err != nil {
return err
}
s.session.Serve(mux.New( s.session.Serve(mux.New(
mux.MessageFunc("", xml.Name{Local: "subject"}, s.message), mux.MessageFunc("", xml.Name{Local: "subject"}, s.message),
mux.PresenceFunc(stanza.SubscribePresence, xml.Name{}, s.autoSubscribe),
)) ))
return nil return nil
} }
// autoSubscribe to allow sending IQ
func (s *XMPPService) autoSubscribe(presHead stanza.Presence, t xmlstream.TokenReadEncoder) error {
log.WithField("p", presHead).Info("autoSubscribe")
t.Encode(stanza.Presence{
Type: stanza.SubscribedPresence,
To: presHead.From,
})
return nil
}
// handler of incoming message - forward to DBUS // handler of incoming message - forward to DBUS
func (s *XMPPService) message(msgHead stanza.Message, t xmlstream.TokenReadEncoder) error { func (s *XMPPService) message(msgHead stanza.Message, t xmlstream.TokenReadEncoder) error {
d := xml.NewTokenDecoder(t) d := xml.NewTokenDecoder(t)
@ -121,6 +102,7 @@ func (s *XMPPService) message(msgHead stanza.Message, t xmlstream.TokenReadEncod
return nil return nil
} }
// Register handler of DBUS Distribution // Register handler of DBUS Distribution
func (s *XMPPService) Register(appName, token string) (string, string, error) { func (s *XMPPService) Register(appName, token string) (string, string, error) {
logger := log.WithFields(map[string]interface{}{ logger := log.WithFields(map[string]interface{}{
@ -130,11 +112,11 @@ func (s *XMPPService) Register(appName, token string) (string, string, error) {
iq := messages.RegisterIQ{ iq := messages.RegisterIQ{
IQ: stanza.IQ{ IQ: stanza.IQ{
Type: stanza.SetIQ, Type: stanza.SetIQ,
To: jid.MustParse(s.Gateway), To: jid.MustParse(s.Gateway),
}, },
} }
externalToken := fmt.Sprintf("%s/%s", appName, token) externalToken := fmt.Sprintf("%s/%s", appName, token)
iq.Register.Token = &messages.TokenData{ Body: externalToken } iq.Register.Token = &messages.TokenData{Body: externalToken}
t, err := s.session.EncodeIQ(context.TODO(), iq) t, err := s.session.EncodeIQ(context.TODO(), iq)
if err != nil { if err != nil {
logger.Errorf("xmpp send IQ for register: %v", err) logger.Errorf("xmpp send IQ for register: %v", err)

View File

@ -25,3 +25,5 @@ require (
) )
replace dev.sum7.eu/genofire/unified-push-xmpp/messages => ../messages replace dev.sum7.eu/genofire/unified-push-xmpp/messages => ../messages
replace mellium.im/xmpp => ../../../../mellium.im/xmpp

View File

@ -2,14 +2,14 @@ package main
import ( import (
"context" "context"
"crypto/tls"
"encoding/xml" "encoding/xml"
"io" "io"
"net"
"github.com/bdlm/log" "github.com/bdlm/log"
"mellium.im/sasl"
"mellium.im/xmlstream" "mellium.im/xmlstream"
"mellium.im/xmpp" "mellium.im/xmpp"
"mellium.im/xmpp/component"
"mellium.im/xmpp/jid" "mellium.im/xmpp/jid"
"mellium.im/xmpp/mux" "mellium.im/xmpp/mux"
"mellium.im/xmpp/stanza" "mellium.im/xmpp/stanza"
@ -18,27 +18,23 @@ import (
) )
type XMPPService struct { type XMPPService struct {
Login string Addr string `toml:"address"`
Password string JID string `toml:"jid"`
Secret string `toml:"secret"`
session *xmpp.Session session *xmpp.Session
} }
func (s *XMPPService) Run() error { func (s *XMPPService) Run() error {
var err error var err error
j := jid.MustParse(s.Login) j := jid.MustParse(s.JID)
if s.session, err = xmpp.DialClientSession( ctx := context.TODO()
context.TODO(), j, conn, err := net.Dial("tcp", s.Addr)
xmpp.BindCustom(func(i jid.JID,r string) (jid.JID, error) { if err != nil {
// Never run return err
log.Infof("try to bind: %v with ressource %s", i, r) }
return j, nil if s.session, err = component.NewSession(
}), ctx, j.Domain(),
xmpp.StartTLS(&tls.Config{ []byte(s.Secret), conn,
ServerName: j.Domain().String(),
}),
// sasl.ScramSha1Plus <- problem with (my) ejabberd
//xmpp.SASL("", xs.Password, sasl.ScramSha1Plus, sasl.ScramSha1, sasl.Plain),
xmpp.SASL("", s.Password, sasl.ScramSha1, sasl.Plain),
); err != nil { ); err != nil {
return err return err
} }
@ -52,38 +48,27 @@ func (s *XMPPService) Run() error {
log.Errorf("Error closing connection: %q", err) log.Errorf("Error closing connection: %q", err)
} }
}() }()
// Send initial presence to let the server know we want to receive messages. /* Send initial presence to let the server know we want to receive messages.
err = s.session.Send(context.TODO(), stanza.Presence{Type: stanza.AvailablePresence}.Wrap(nil)) err = s.session.Send(context.TODO(), stanza.Presence{Type: stanza.AvailablePresence}.Wrap(nil))
if err != nil { if err != nil {
return err return err
} }*/
log.Infof("connected with %s", s.session.LocalAddr()) log.Infof("connected with %s", s.session.LocalAddr())
s.session.Serve(mux.New( return s.session.Serve(mux.New(
// register - get + set // register - get + set
mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s.handleRegister), mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s.handleRegister),
mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s.handleRegister), mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s.handleRegister),
// unregister - get + set // unregister - get + set
mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister), mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister),
mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister), mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister),
// auto accept // mux.IQFunc("", xml.Name{}, s.handleDisco),
mux.PresenceFunc(stanza.SubscribePresence, xml.Name{}, s.autoSubscribe),
)) ))
return nil /* -
} return s.session.Serve(xmpp.HandlerFunc(func(t xmlstream.TokenReadEncoder, start *xml.StartElement) error {
// autoSubscribe to allow sending IQ log.Info(start)
func (s *XMPPService) autoSubscribe(presHead stanza.Presence, t xmlstream.TokenReadEncoder) error { return nil
log.WithField("p", presHead).Info("autoSubscribe") }))
// request eighter */
t.Encode(stanza.Presence{
Type: stanza.SubscribePresence,
To: presHead.From,
})
// agree
t.Encode(stanza.Presence{
Type: stanza.SubscribedPresence,
To: presHead.From,
})
return nil
} }
func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error { func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error {
@ -91,12 +76,13 @@ func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder,
IQ: stanza.IQ{ IQ: stanza.IQ{
ID: iq.ID, ID: iq.ID,
Type: stanza.ErrorIQ, Type: stanza.ErrorIQ,
From: iq.To,
To: iq.From, To: iq.From,
}, },
} }
defer func(){ defer func() {
if err := t.Encode(reply); err != nil { if err := t.Encode(reply); err != nil {
log.Errorf("sending response: %v", err) log.Errorf("sending register response: %v", err)
} }
}() }()
log.Infof("recieved iq: %v", iq) log.Infof("recieved iq: %v", iq)
@ -104,19 +90,19 @@ func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder,
tokenData := messages.TokenData{} tokenData := messages.TokenData{}
err := xml.NewTokenDecoder(t).Decode(&tokenData) err := xml.NewTokenDecoder(t).Decode(&tokenData)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
log.Errorf("Error decoding message: %q", err) log.Errorf("decoding message: %q", err)
reply.Register.Error = &messages.ErrorData{ Body: "unable decode"} reply.Register.Error = &messages.ErrorData{Body: "unable decode"}
return nil return nil
} }
token := tokenData.Body token := tokenData.Body
if token == "" { if token == "" {
log.Errorf("no token found: %v", token) log.Errorf("no token found: %v", token)
reply.Register.Error = &messages.ErrorData{ Body: "no token"} reply.Register.Error = &messages.ErrorData{Body: "no token"}
return nil return nil
} }
endpoint := "https://localhost/UP?token=" + token + "&to=" +iq.From.String() endpoint := "https://localhost/UP?token=" + token + "&to=" + iq.From.String()
reply.IQ.Type = stanza.ResultIQ reply.IQ.Type = stanza.ResultIQ
reply.Register.Endpoint = &messages.EndpointData{ Body: endpoint} reply.Register.Endpoint = &messages.EndpointData{Body: endpoint}
log.Infof("generate respone: %v", endpoint) log.Infof("generate respone: %v", endpoint)
return nil return nil
} }
@ -125,17 +111,34 @@ func (s *XMPPService) handleUnregister(iq stanza.IQ, t xmlstream.TokenReadEncode
IQ: stanza.IQ{ IQ: stanza.IQ{
ID: iq.ID, ID: iq.ID,
Type: stanza.ErrorIQ, Type: stanza.ErrorIQ,
From: iq.To,
To: iq.From, To: iq.From,
}, },
} }
defer func(){ defer func() {
if err := t.Encode(reply); err != nil {
log.Errorf("sending unregister response: %v", err)
}
}()
log.Infof("unregistered unhandled: %v", start)
reply.Unregister.Error = "not implemented"
return nil
}
func (s *XMPPService) handleDisco(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error {
reply := stanza.IQ{
ID: iq.ID,
Type: stanza.ErrorIQ,
From: iq.To,
To: iq.From,
}
defer func() {
if err := t.Encode(reply); err != nil { if err := t.Encode(reply); err != nil {
log.Errorf("sending response: %v", err) log.Errorf("sending response: %v", err)
} }
}() }()
log.Infof("unhandled: %v", start) log.Infof("recieved iq: %v", iq)
reply.Unregister.Error = "not implemented"
return nil return nil
} }
@ -143,7 +146,8 @@ func (s *XMPPService) handleUnregister(iq stanza.IQ, t xmlstream.TokenReadEncode
func (s *XMPPService) SendMessage(to, token, content string) error { func (s *XMPPService) SendMessage(to, token, content string) error {
return s.session.Encode(context.TODO(), messages.Message{ return s.session.Encode(context.TODO(), messages.Message{
Message: stanza.Message{ Message: stanza.Message{
To: jid.MustParse(to), To: jid.MustParse(to),
From: jid.MustParse(s.JID),
// Type: stanza.ChatMessage, // Type: stanza.ChatMessage,
Type: stanza.NormalMessage, Type: stanza.NormalMessage,
}, },

View File

@ -17,27 +17,27 @@ const (
// RegisterIQ with stanza // RegisterIQ with stanza
type RegisterIQ struct { type RegisterIQ struct {
stanza.IQ stanza.IQ
Register struct{ Register struct {
XMLName xml.Name `xml:"unifiedpush.org register"` XMLName xml.Name `xml:"unifiedpush.org register"`
Token *TokenData `xml:"token"` Token *TokenData `xml:"token"`
Endpoint *EndpointData `xml:"endpoint"` Endpoint *EndpointData `xml:"endpoint"`
Error *ErrorData `xml:"error"` Error *ErrorData `xml:"error"`
} `xml:"register"` } `xml:"register"`
} }
type TokenData struct { type TokenData struct {
XMLName xml.Name `xml:"token"` XMLName xml.Name `xml:"token"`
Body string `xml:",chardata"` Body string `xml:",chardata"`
} }
type EndpointData struct { type EndpointData struct {
XMLName xml.Name `xml:"endpoint"` XMLName xml.Name `xml:"endpoint"`
Body string `xml:",chardata"` Body string `xml:",chardata"`
} }
type ErrorData struct { type ErrorData struct {
XMLName xml.Name `xml:"error"` XMLName xml.Name `xml:"error"`
Body string `xml:",chardata"` Body string `xml:",chardata"`
} }
// UnregisterIQ with stanza // UnregisterIQ with stanza