Reworked the ping functions and stanza processing.

This commit is contained in:
Martin Dosch 2018-08-08 11:46:58 +02:00
parent 3bdfea029e
commit 5a5014d449

View file

@ -16,9 +16,17 @@ import (
"github.com/mattn/go-xmpp" "github.com/mattn/go-xmpp"
) )
// Variables defined globally as they are used by functions pingMUC
// and processStanzas.
var (
id string
err error
pingSent time.Time
pingReceived bool
)
func main() { func main() {
var err error
var configPath, configFile string var configPath, configFile string
type configuration struct { type configuration struct {
@ -132,6 +140,9 @@ func main() {
// Starting goroutine to ping the MUC every 30 seconds. // Starting goroutine to ping the MUC every 30 seconds.
go pingMUC(client, config.BotJid, config.Muc, config.MucNick) go pingMUC(client, config.BotJid, config.Muc, config.MucNick)
// Starting goroutine to process received stanzas.
go processStanzas(client)
for { for {
// Check all configured feeds for new articles and send // Check all configured feeds for new articles and send
// new articles to configured MUC. // new articles to configured MUC.
@ -163,59 +174,22 @@ func pingMUC(client *xmpp.Client, botJid string, Muc string, MucNick string) {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
// Send ping to own MUC participant to check we are still joined. // Send ping to own MUC participant to check we are still joined.
id, err := client.RawInformation(botJid, Muc+"/"+MucNick, sid.Id(), id, err = client.RawInformation(botJid, Muc+"/"+MucNick, sid.Id(),
"get", "<ping xmlns='urn:xmpp:ping'/>") "get", "<ping xmlns='urn:xmpp:ping'/>")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
pingSent := time.Now() pingSent = time.Now()
pingReceived := false pingReceived = false
// Check for result IQ as long as there was no reply yet. // Check for result IQ as long as there was no reply yet.
for (time.Since(pingSent).Seconds() < 10.0) && (pingReceived == false) { for (time.Since(pingSent).Seconds() < 10.0) && (pingReceived == false) {
// Receive stanzas. ToDo: Receive stanzas continiously without 30s delay. time.Sleep(1 * time.Second)
stanza, err := client.Recv() if pingReceived == true {
if err != nil {
log.Fatal(err)
}
// Check IQs for ping results and disco#info queries.
switch v := stanza.(type) {
case xmpp.IQ:
if (v.Type == "error") && (v.ID == id) {
log.Fatal("MUC not available.")
}
if (v.Type == "result") && (v.ID == id) {
pingReceived = true
}
if v.Type == "get" {
// Reply to disco#info requests according to https://xmpp.org/extensions/xep-0030.html.
if strings.Contains(string(v.Query),
"<query xmlns='http://jabber.org/protocol/disco#info'/>") == true {
_, err := client.RawInformation(client.JID(), v.From, v.ID,
"result", "<query xmlns='http://jabber.org/protocol/disco#info'>"+
"<identity category='client' type='bot' name='feedbot'/>"+
"<feature var='http://jabber.org/protocol/disco#info'/></query>")
if err != nil {
log.Fatal(err)
}
} else {
// Send error replies for all other IQs.
_, err := client.RawInformation(client.JID(), v.From, v.ID, "error", string(v.Query)+
"<error type='cancel'><feature-not-implemented "+
"xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><error/>")
if err != nil {
log.Fatal(err)
}
}
}
default:
break break
} }
} }
// Quit if no ping reply was received. // Quit if no ping reply was received.
if pingReceived == false { if pingReceived == false {
@ -236,3 +210,55 @@ func pingServer(client *xmpp.Client, server string, botJid string) {
} }
} }
} }
func processStanzas(client *xmpp.Client) {
for { // Receive stanzas. ToDo: Receive stanzas continiously without 30s delay.
stanza, err := client.Recv()
if err != nil {
log.Fatal(err)
}
// Check IQs for ping results and disco#info queries.
switch v := stanza.(type) {
case xmpp.IQ:
if (v.Type == "error") && (v.ID == id) {
log.Fatal("MUC not available.")
}
if (v.Type == "result") && (v.ID == id) {
pingReceived = true
}
if v.Type == "get" {
// Reply to disco#info requests according to https://xmpp.org/extensions/xep-0030.html.
if strings.Contains(string(v.Query),
"<query xmlns='http://jabber.org/protocol/disco#info'/>") == true {
_, err := client.RawInformation(client.JID(), v.From, v.ID,
"result", "<query xmlns='http://jabber.org/protocol/disco#info'>"+
"<identity category='client' type='bot' name='feedbot'/>"+
"<feature var='http://jabber.org/protocol/disco#info'/></query>")
if err != nil {
log.Fatal(err)
}
} else if strings.Contains(string(v.Query), "<ping xmlns='urn:xmpp:ping'/>") == true {
// Reply to pings.
_, err := client.RawInformation(client.JID(), v.From, v.ID, "result", "")
if err != nil {
log.Fatal(err)
}
} else {
// Send error replies for all other IQs.
_, err := client.RawInformation(client.JID(), v.From, v.ID, "error",
"<error type='cancel'><service-unavailable "+
"xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error>")
if err != nil {
log.Fatal(err)
}
}
}
default:
break
}
}
}