X-Git-Url: https://git.realraum.at/?a=blobdiff_plain;f=go%2Fr3-netstatus%2Fr3xmppbot%2Fr3xmppbot.go;h=3ad4177c0ffec3cb9fbe0d4cd632881d784c70d9;hb=3ccab0493b7a182ef2efce4cfffb1e5107eab14b;hp=141e5418272d4ecc00b1b46463b935b8809f7733;hpb=fa43684a042825be410260f547e092be3b432317;p=svn42.git diff --git a/go/r3-netstatus/r3xmppbot/r3xmppbot.go b/go/r3-netstatus/r3xmppbot/r3xmppbot.go index 141e541..3ad4177 100644 --- a/go/r3-netstatus/r3xmppbot/r3xmppbot.go +++ b/go/r3-netstatus/r3xmppbot/r3xmppbot.go @@ -11,18 +11,6 @@ import ( "path" ) -//~ type StdLogger struct { -//~ } - -//~ func (s *StdLogger) Log(v ...interface{}) { - //~ log.Println(v...) -//~ } - -//~ func (s *StdLogger) Logf(fmt string, v ...interface{}) { - //~ log.Printf(fmt, v...) -//~ } - - func (botdata *XmppBot) makeXMPPMessage(to string, message interface{}, subject interface{}) *xmpp.Message { xmppmsgheader := xmpp.Header{To: to, From: botdata.my_jid_, @@ -171,26 +159,21 @@ func (data RealraumXmppNotifierConfig) loadFrom(filepath string) () { } } - -func init() { - //~ logger := &StdLogger{} - //~ xmpp.Debug = logger - //~ xmpp.Info = logger - //~ xmpp.Warn = logger -} - func (botdata *XmppBot) handleEventsforXMPP(xmppout chan <- xmpp.Stanza, presence_events <- chan interface{}, jabber_events <- chan JabberEvent) { var last_status_msg *string defer func() { if x := recover(); x != nil { Syslog_.Printf("handleEventsforXMPP: run time panic: %v", x) + //FIXME: signal that xmpp bot has crashed } + for _ = range(jabber_events) {} //cleanout jabber_events queue }() for { select { - case pe := <-presence_events: + case pe, pe_still_open := <-presence_events: + if ! pe_still_open { return } Debug_.Printf("handleEventsforXMPP<-presence_events: %T %+v", pe, pe) switch pec := pe.(type) { case xmpp.Stanza: @@ -216,19 +199,21 @@ func (botdata *XmppBot) handleEventsforXMPP(xmppout chan <- xmpp.Stanza, presenc } } default: - break + Debug_.Println("handleEventsforXMPP<-presence_events: unknown type received: quitting") + return } - case je := <-jabber_events: + case je, je_still_open := <-jabber_events: + if ! je_still_open { return } Debug_.Printf("handleEventsforXMPP<-jabber_events: %T %+v", je, je) simple_jid := removeJIDResource(je.JID) jid_data, jid_in_map := botdata.realraum_jids_[simple_jid] - + //send status if requested, even if user never changed any settings and thus is not in map if last_status_msg != nil && je.StatusNow { xmppout <- botdata.makeXMPPMessage(je.JID, last_status_msg, nil) } - + if jid_in_map { //if R3OnlineOnlyWithRecapInfo, we want a status update when coming online if last_status_msg != nil && ! jid_data.Online && je.Online && jid_data.Wants == R3OnlineOnlyWithRecapInfo { @@ -323,19 +308,46 @@ func (botdata *XmppBot) handleIncomingXMPPStanzas(xmppin <- chan xmpp.Stanza, xm defer func() { if x := recover(); x != nil { Syslog_.Printf("handleIncomingXMPPStanzas: run time panic: %v", x) - close(jabber_events) } + close(jabber_events) }() + var error_count int = 0 var incoming_stanza interface{} + + handleStanzaError := func() bool { + error_count++ + if error_count > 15 { + Syslog_.Println("handleIncomingXMPPStanzas: too many errors in series.. bailing out") + botdata.StopBot() + return true + } + return false + } + for incoming_stanza = range xmppin { switch stanza := incoming_stanza.(type) { case *xmpp.Message: + if stanza.GetHeader() == nil { continue } + if stanza.Type == "error" || stanza.Error != nil { + Syslog_.Printf("XMPP %T Error: %s", stanza, stanza) + if stanza.Error.Type == "cancel" { + // asume receipient not reachable -> disable + Syslog_.Printf("Error reaching %s. Disabling user, please reenable manually", stanza.From) + jabber_events <- JabberEvent{stanza.From, false, R3NeverInfo, false} + continue + } + if handleStanzaError() { return } + continue + } else { error_count = 0 } botdata.handleIncomingMessageDialog(*stanza, xmppout, jabber_events) case *xmpp.Presence: - if stanza.GetHeader() == nil { + if stanza.GetHeader() == nil { continue } + if stanza.Type == "error" || stanza.Error != nil { + Syslog_.Printf("XMPP %T Error: %s", stanza, stanza) + if handleStanzaError() { return } continue - } + } else { error_count = 0 } switch stanza.GetHeader().Type { case "subscribe": xmppout <- botdata.makeXMPPPresence(stanza.GetHeader().From, "subscribed", "", "") @@ -351,14 +363,27 @@ func (botdata *XmppBot) handleIncomingXMPPStanzas(xmppin <- chan xmpp.Stanza, xm default: jabber_events <- JabberEvent{stanza.GetHeader().From, true, R3NoChange, false} } + case *xmpp.Iq: - if stanza.GetHeader() == nil { + if stanza.GetHeader() == nil { continue } + if stanza.Type == "error" || stanza.Error != nil { + Syslog_.Printf("XMPP %T Error: %s", stanza, stanza) + if handleStanzaError() { return } continue - } + } else { error_count = 0 } + + if HandleServerToClientPing(stanza, xmppout) {continue} //if true then routine handled it and we can continue + Debug_.Printf("Unhandled Iq: %s", stanza) } } } +func init() { + //~ xmpp.Debug = &XMPPDebugLogger{} + xmpp.Info = &XMPPDebugLogger{} + xmpp.Warn = &XMPPLogger{} +} + func NewStartedBot(loginjid, loginpwd, password, state_save_dir string, insecuretls bool) (*XmppBot, chan interface{}, error) { var err error botdata := new(XmppBot) @@ -373,11 +398,6 @@ func NewStartedBot(loginjid, loginpwd, password, state_save_dir string, insecure botdata.config_file_ = path.Join(state_save_dir, "r3xmpp."+removeJIDResource(loginjid)+".json") - //~ logger := &StdLogger{} - //~ xmpp.Debug = logger - //~ xmpp.Info = logger - //~ xmpp.Warn = logger - xmpp.TlsConfig = tls.Config{InsecureSkipVerify: insecuretls} botdata.realraum_jids_.loadFrom(botdata.config_file_) @@ -418,6 +438,7 @@ func NewStartedBot(loginjid, loginpwd, password, state_save_dir string, insecure } func (botdata *XmppBot) StopBot() { + Syslog_.Println("Stopping XMPP Bot") if botdata.xmppclient_ != nil { close(botdata.xmppclient_.Out) } @@ -425,4 +446,7 @@ func (botdata *XmppBot) StopBot() { *botdata.presence_events_ <- false close(*botdata.presence_events_) } + botdata.config_file_ = "" + botdata.realraum_jids_ = nil + botdata.xmppclient_ = nil }