diff options
| -rw-r--r-- | xmpp/conn.go | 96 | ||||
| -rw-r--r-- | xmpp/decoder.go | 57 | ||||
| -rw-r--r-- | xmpp/encoder.go | 79 | ||||
| -rw-r--r-- | xmpp/routing.go | 104 | ||||
| -rw-r--r-- | xmpp/sasl.go | 59 | ||||
| -rw-r--r-- | xmpp/session.go | 18 | ||||
| -rw-r--r-- | xmpp/stream.go | 42 | 
7 files changed, 5 insertions, 450 deletions
diff --git a/xmpp/conn.go b/xmpp/conn.go deleted file mode 100644 index f017889..0000000 --- a/xmpp/conn.go +++ /dev/null @@ -1,96 +0,0 @@ -package xmpp - -import ( -	"crypto/tls" -	"crypto/x509" -	"log" -) - -type Event uint8 - -const ( -	DisconnectEvent Event = iota -	ConnectEvent -	ShouldDisconnectEvent -) - -type Conn struct { -	ch chan Event -	jid, pwd string -	tcp *tls.Conn -	enc encoder -} - -func NewConn(ch chan Event, jid string, pwd string) *Conn { -	c := Conn{ -		ch: ch, -		jid: jid, -		pwd: pwd} - -	return &c -} - -func (c *Conn) Connect() error { -	var err error - -	domain := domainpart(c.jid) - -	roots, err := x509.SystemCertPool() -	if err != nil { -		log.Println(err) -		return err -	} - -	c.tcp, err = tls.Dial("tcp", domain+":"+"5223", &tls.Config{RootCAs: roots}) -	if err != nil { -		log.Println(err) -		return err -	} - -	return nil -} - -func (c *Conn) Disconnect() { -	c.tcp.Close() -} - -func (c *Conn) Run() { -	err := c.Connect() -	if err != nil { -		return -	} -	defer c.Disconnect() - -	decoder := newDecoder(c.tcp) -	go decoder.run() -	defer decoder.stop() - -	c.enc = newEncoder(c.tcp) -	defer c.enc.Close() - -	tr := newTokenRouter() - -	end := sendStreamStart(&c.enc, c.jid) -	defer sendStreamEnd(&c.enc, end) - -	c.ch <- ConnectEvent -	defer func() { c.ch <- DisconnectEvent }() - -	for { -		select { -		case ev := <-c.ch: -			switch ev { -			case ShouldDisconnectEvent: -				return -			default: -				log.Printf("Unknown Event '%d'!\n", ev) -			} -		case token := <-decoder.data: -			err = tr.route(token, c) -			if err != nil { -				log.Println(err) -				return -			} -		} -	} -} diff --git a/xmpp/decoder.go b/xmpp/decoder.go deleted file mode 100644 index 7139b5a..0000000 --- a/xmpp/decoder.go +++ /dev/null @@ -1,57 +0,0 @@ -package xmpp - -import ( -	"crypto/tls" -	"encoding/xml" -	"log" -	"os" -) - -type decoder struct { -	terminator chan bool -	data chan xml.Token -	decoder *xml.Decoder -	debug *xml.Encoder -} - -func newDecoder(conn *tls.Conn) decoder { -	d := decoder{ -		make(chan bool), -		make(chan xml.Token), -		xml.NewDecoder(conn), -		xml.NewEncoder(os.Stdout), -	} - -	d.debug.Indent("S: ", "    ") - -	return d -} - -func (r *decoder) run() { -	for { -		select { -		case <-r.terminator: -			return -		default: -			t, err := r.decoder.Token() -			if t != nil && err == nil { -				err := r.debug.EncodeToken(t) -				if err != nil { -					log.Println("Could not encode received XML token to debug output!") -				} -				err = r.debug.Flush() -				if err != nil { -					log.Println("Could not flush debug output after receive!") -				} -				r.data <- xml.CopyToken(t) -			} -			if err != nil { -				return  // FIXME disconnect on parsing error -			} -		} -	} -} - -func (r *decoder) stop() { -	r.terminator <- true -} diff --git a/xmpp/encoder.go b/xmpp/encoder.go deleted file mode 100644 index 434ca68..0000000 --- a/xmpp/encoder.go +++ /dev/null @@ -1,79 +0,0 @@ -package xmpp - -import ( -	"crypto/tls" -	"encoding/xml" -	"os" -) - -type encoder struct { -	tcp *xml.Encoder -	debug *xml.Encoder -} - -func newEncoder(conn *tls.Conn) encoder { -	e := encoder{ -		xml.NewEncoder(conn), -		xml.NewEncoder(os.Stdout), -	} -	e.tcp.Indent("", "") -	e.debug.Indent("C: ", "    ") - -	return e -} - -func (e *encoder) encodeNow(t xml.Token) error { -	err := e.encode(t) -	if err != nil { -		return err -	} - -	err = e.flush() -	if err != nil { -		return err -	} - -	return nil -} - -func (e *encoder) encode(t xml.Token) error { -	err := e.tcp.EncodeToken(t) -	if err != nil { -		return err -	} - -	err = e.debug.EncodeToken(t) -	if err != nil { -		return err -	} - -	return nil -} - -func (e *encoder) flush() error { -	err := e.tcp.Flush() -	if err != nil { -		return err -	} - -	err = e.debug.Flush() -	if err != nil { -		return err -	} - -	return nil -} - -func (e *encoder) Close() error { -	err := e.tcp.Close() -	if err != nil { -		return err -	} - -	err = e.debug.Close() -	if err != nil { -		return err -	} - -	return nil -} diff --git a/xmpp/routing.go b/xmpp/routing.go deleted file mode 100644 index 9199874..0000000 --- a/xmpp/routing.go +++ /dev/null @@ -1,104 +0,0 @@ -package xmpp - -import ( -	"encoding/xml" -	"errors" -	"log" -) - -type tokenRouter struct { -	start        xml.StartElement -	end          xml.EndElement -	buffer       []xml.Token -	level        uint16 // XML nesting level -	enc          *encoder -} - -func newTokenRouter() tokenRouter { -	return tokenRouter{ -		buffer: make([]xml.Token, 0), -		level:  0, -	} -} - -func (r *tokenRouter) route(t xml.Token, c *Conn) error { -	r.buffer = append(r.buffer, t) - -	switch unwrapped := t.(type) { -	case xml.StartElement: -		r.level += 1 -		if r.level == 1 { -			r.start = unwrapped -			r.buffer = r.buffer[:0] -			// call start handler -		} -	case xml.EndElement: -		if r.level == 0 { -			log.Println("Ignoring XML end element on nesting level zero") -			return nil -		} -		r.level -= 1 -		switch r.level { -		case 0: -			return errors.New("Stream was closed by server") -		case 1: -			err := routeElement(r.buffer, c) -			if err != nil { -				return err -			} -			r.buffer = r.buffer[:0] -		} -	case xml.ProcInst: -		log.Println("Ignoring xml.ProcInst element") -		r.buffer = r.buffer[:len(r.buffer)-1] -	case xml.Directive: -		log.Println("Ignoring xml.Directive element") -		r.buffer = r.buffer[:len(r.buffer)-1] -	case xml.Comment: -		log.Println("Ignoring xml.Comment element") -		r.buffer = r.buffer[:len(r.buffer)-1] -	} - -	return nil -} - -func routeElement(b []xml.Token, c *Conn) error { -	tab := elementRoutingTable{ -		{xml.Name{"http://etherx.jabber.org/streams", "features"}, streamFeatures}, -		{xml.Name{"urn:ietf:params:xml:ns:xmpp-sasl", "success"}, onSaslSuccess}, -		{xml.Name{"urn:ietf:params:xml:ns:xmpp-sasl", "failure"}, onSaslFailure}, -	} - -	switch unwrapped := b[0].(type) { -	case xml.StartElement: -		for _, v := range(tab) { -			if unwrapped.Name == v.name { -				err := v.handler(b, c) -				if err != nil { -					return err -				} -				return nil -			} -		} -		log.Printf("Ignoring XML element '%s' from namespace '%s'", -		           unwrapped.Name.Local, unwrapped.Name.Space) -	default: -		log.Println("Ignoring XML element which has no StartElement as first token") -	} - -	return nil -} - -type elementRoutingTable []struct { -	name    xml.Name -	handler func(b []xml.Token, c *Conn) error -} - -func streamFeatures(b []xml.Token, c *Conn) error { -	err := sendSaslAuth(b, c) -	if err != nil { -		return err -	} - -	return nil -} diff --git a/xmpp/sasl.go b/xmpp/sasl.go deleted file mode 100644 index 91cbf6b..0000000 --- a/xmpp/sasl.go +++ /dev/null @@ -1,59 +0,0 @@ -package xmpp - -import ( -	"encoding/xml" -	"encoding/base64" -	"errors" -) - -func sendSaslAuth(b []xml.Token, c *Conn) error { -	mechanisms := make([]string, 0) -	for i, v := range(b) { -		switch token := v.(type) { -		case xml.StartElement: -			expected := xml.Name{"urn:ietf:params:xml:ns:xmpp-sasl", "mechanism"} -			if token.Name == expected { -				if i >= (len(b)-1) { continue } -				switch payload := b[i+1].(type) { -				case xml.CharData: -					mechanisms = append(mechanisms, string(payload)) -				} -			} -		} -	} - -	for _, v := range(mechanisms) { -		if v == "PLAIN" { -			start := xml.StartElement{ -				xml.Name{"urn:ietf:params:xml:ns:xmpp-sasl", "auth"}, -				[]xml.Attr{ -					xml.Attr{xml.Name{"", "mechanism"}, "PLAIN"}, -				}, -			} - -			data := []byte("\x00" + username(c.jid) + "\x00" + c.pwd) -			dst := make([]byte, base64.StdEncoding.EncodedLen(len(data))) -			base64.StdEncoding.Encode(dst, data) -			payload := xml.CharData(dst) - -			end := start.End() - -			c.enc.encodeNow(start) -			c.enc.encode(payload) -			c.enc.encodeNow(end) - -			return nil -		} -	} - -	return errors.New("No compatible SASL mechanism given") -} - -func onSaslSuccess(b []xml.Token, c *Conn) error { -	sendStreamStart(&c.enc, c.jid) -	return nil -} - -func onSaslFailure(b []xml.Token, c *Conn) error { -	return errors.New("Authentication failed") -} diff --git a/xmpp/session.go b/xmpp/session.go index 2162d66..e928f01 100644 --- a/xmpp/session.go +++ b/xmpp/session.go @@ -16,8 +16,8 @@ type session struct {  	in, out   chan any  	transport *tls.Conn  	ed        encoderDecoder -	streams   []stream  	rx        chan xml.Token +	streamEnd xml.EndElement  }  func StartSession(out chan any, jid string, pwd string) chan any { @@ -26,7 +26,6 @@ func StartSession(out chan any, jid string, pwd string) chan any {  	s.jid = jid  	s.in = make(chan any)  	s.out = out -	s.streams = make([]stream, 0)  	s.rx = make(chan xml.Token, 0)  	go s.run() @@ -82,9 +81,6 @@ func (s *session) startTransport() error {  }  func (s *session) openStream() { -	stream := stream{} -	stream.session = s -  	start := xml.StartElement{  		xml.Name{"jabber:client", "stream:stream"},  		[]xml.Attr{ @@ -96,21 +92,17 @@ func (s *session) openStream() {  		},  	} -	stream.end = start.End() +	s.streamEnd = start.End()  	err := s.ed.encodeToken(start)  	if err != nil {  		log.Println("Could not encode stream start!")  	} - -	s.streams = append(s.streams, stream)  }  func (s *session) closeStreams() { -	for { -		limit := len(s.streams) -		if limit <= 0 { break } -		s.streams[limit - 1].terminate() -		s.streams = s.streams[:limit - 1] +	err := s.ed.encodeToken(s.streamEnd) +	if err != nil { +		log.Println("Could not encode stream end!")  	}  } diff --git a/xmpp/stream.go b/xmpp/stream.go deleted file mode 100644 index d0680aa..0000000 --- a/xmpp/stream.go +++ /dev/null @@ -1,42 +0,0 @@ -package xmpp - -import ( -	"encoding/xml" -	"log" -) - -type stream struct { -	session *session -	end     xml.EndElement -} - -func (s *stream) terminate() { -	s.session.ed.encodeToken(s.end) -} - -func sendStreamStart(enc *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.encodeNow(start) -	if err != nil { -		log.Println("Could not encode stream start!") -	} - -	return start.End() -} - -func sendStreamEnd(enc *encoder, end xml.EndElement) { -	err := enc.encodeNow(end) -	if err != nil { -		log.Println("Could not encode stream end!") -	} -}  | 
