summaryrefslogtreecommitdiff
path: root/xmpp.go
diff options
context:
space:
mode:
authorxengineering <me@xengineering.eu>2023-05-15 21:09:26 +0200
committerxengineering <me@xengineering.eu>2023-05-15 21:09:26 +0200
commit8023777ac1b0171783e1c55f67a6179d63708272 (patch)
tree38b43dff5cb3e846f018f9b77c0c76734bb0f832 /xmpp.go
parent1769afe3009b5b3cfa3beb3dcf051e41487be113 (diff)
downloadlimox-8023777ac1b0171783e1c55f67a6179d63708272.tar
limox-8023777ac1b0171783e1c55f67a6179d63708272.tar.zst
limox-8023777ac1b0171783e1c55f67a6179d63708272.zip
Introduce package xengineering.eu/limox/xmpp
The XMPP logic is now big enough to create a corresponding package for it.
Diffstat (limited to 'xmpp.go')
-rw-r--r--xmpp.go187
1 files changed, 0 insertions, 187 deletions
diff --git a/xmpp.go b/xmpp.go
deleted file mode 100644
index a0aaba7..0000000
--- a/xmpp.go
+++ /dev/null
@@ -1,187 +0,0 @@
-package main
-
-import (
- "crypto/tls"
- "crypto/x509"
- "encoding/xml"
- "log"
- "os"
-)
-
-type XmppEvent uint8
-
-const (
- XmppDisconnect XmppEvent = iota
- XmppConnect
-)
-
-func xmpp(rxChan chan GuiEvent, txChan chan any, jid string, pwd string) {
- conn, err := setupConn(jid)
- if err != nil {
- log.Print(err)
- return
- }
- defer conn.Close()
-
- receiver := newXmppReceiver(conn)
- go receiver.run()
- defer receiver.stop()
-
- enc := xml.NewEncoder(conn)
- defer enc.Close()
- dbg := xml.NewEncoder(os.Stdout)
- defer dbg.Close()
-
- end := sendStreamStart(enc, dbg, jid)
- defer sendStreamEnd(enc, dbg, end)
-
- txChan <- XmppConnect
- defer func() { txChan <- XmppDisconnect }()
-
- for {
- select {
- case ev := <-rxChan:
- switch ev {
- case Disconnect:
- return
- default:
- log.Printf("Unknown GuiEvent '%d'!\n", ev)
- }
- case rx := <-receiver.data:
- dbg.Indent("S: ", " ")
- dbg.EncodeToken(rx)
- dbg.Flush()
- }
- }
-}
-
-type xmppReceiver struct {
- terminator chan bool
- data chan xml.Token
- decoder *xml.Decoder
-}
-
-func newXmppReceiver(conn *tls.Conn) xmppReceiver {
- return xmppReceiver{
- make(chan bool),
- make(chan xml.Token),
- xml.NewDecoder(conn),
- }
-}
-
-func (r *xmppReceiver) run() {
- for {
- select {
- case <-r.terminator:
- return
- default:
- t, err := r.decoder.Token()
- if err != nil {
- log.Print(err)
- }
- if t != nil {
- c := xml.CopyToken(t)
- r.data <- c
- }
- }
- }
-}
-
-func (r *xmppReceiver) stop() {
- r.terminator <- true
-}
-
-func setupConn(jid string) (*tls.Conn, error) {
- domain := domainpart(jid)
-
- roots, err := x509.SystemCertPool()
- if err != nil {
- return nil, err
- }
-
- return tls.Dial("tcp", domain+":"+"5223", &tls.Config{RootCAs: roots})
-}
-
-func sendStreamStart(enc *xml.Encoder, dbg *xml.Encoder, jid string) xml.EndElement {
- start := xml.StartElement{
- xml.Name{"jabber:client", "stream:stream"},
- []xml.Attr{
- xml.Attr{xml.Name{"", "from"}, jid},
- xml.Attr{xml.Name{"", "to"}, domainpart(jid)},
- xml.Attr{xml.Name{"", "version"}, "1.0"},
- xml.Attr{xml.Name{"", "xml:lang"}, "en"},
- xml.Attr{xml.Name{"", "xmlns:stream"}, "http://etherx.jabber.org/streams"},
- },
- }
-
- err := enc.EncodeToken(start)
- if err != nil {
- log.Println("Could not encode stream start to TCP channel!")
- }
-
- err = enc.Flush()
- if err != nil {
- log.Println("Could not flush TCP channel XML encoder!")
- }
-
- dbg.Indent("C: ", " ")
-
- err = dbg.EncodeToken(start)
- if err != nil {
- log.Println("Could not encode stream start to debug output!")
- }
-
- err = dbg.Flush()
- if err != nil {
- log.Println("Could not flush debug XML encoder!")
- }
-
- return start.End()
-}
-
-func sendStreamEnd(enc *xml.Encoder, dbg *xml.Encoder, end xml.EndElement) {
-
- err := enc.EncodeToken(end)
- if err != nil {
- log.Println("Could not encode stream end to TCP channel!")
- }
-
- err = enc.Flush()
- if err != nil {
- log.Println("Could not flush TCP channel XML encoder!")
- }
-
- dbg.Indent("C: ", " ")
-
- err = dbg.EncodeToken(end)
- if err != nil {
- log.Println("Could not encode stream end to debug output!")
- }
-
- err = dbg.Flush()
- if err != nil {
- log.Println("Could not flush debug XML encoder!")
- }
-}
-
-// domainpart extracts the domain name from a JID / XMPP address. See
-// https://datatracker.ietf.org/doc/html/rfc7622#section-3.2 for details.
-func domainpart(jid string) string {
- list := []rune(jid)
-
- for i, v := range list {
- if v == '/' {
- list = list[:i]
- break
- }
- }
-
- for i, v := range list {
- if v == '@' {
- list = list[i+1:]
- break
- }
- }
-
- return string(list)
-}