forked from genofire/unified-push-xmpp
xmpp works with components (distribute Encoding hangs) - dirty without Webserver, and nice tokens
This commit is contained in:
parent
950a147042
commit
be6e6c4154
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
106
gateway/xmpp.go
106
gateway/xmpp.go
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue