diff options
| -rw-r--r-- | ROADMAP.md | 6 | ||||
| -rw-r--r-- | xmpp/jid.go | 65 | ||||
| -rw-r--r-- | xmpp/router.go | 8 | ||||
| -rw-r--r-- | xmpp/stream_pair.go | 5 | 
4 files changed, 83 insertions, 1 deletions
@@ -7,11 +7,15 @@  - [x] basic XML token logging to console  - [x] infrastructure to route and handle multi-token XML blocks  - [x] SASL authentication -- [ ] ressource binding +- [x] ressource binding  - [ ] sending initial presence  - [ ] roster retrieval  - [ ] single user chat text messages  - [ ] SRV record parsing to get TCP port +- [ ] refactored structure +- [ ] full error handling +- [ ] retries +- [ ] timeouts  ## Basic core compliance diff --git a/xmpp/jid.go b/xmpp/jid.go index 90c1509..0446d19 100644 --- a/xmpp/jid.go +++ b/xmpp/jid.go @@ -1,5 +1,12 @@  package xmpp +import ( +	"encoding/xml" +	"fmt" +	"log" +	"math/rand" +) +  // 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 { @@ -33,3 +40,61 @@ func username(jid string) string {  	return ""  } + +func hasBind(e []xml.Token) bool { +	bind := xml.Name{`urn:ietf:params:xml:ns:xmpp-bind`, `bind`} + +	for _, v := range e { +		switch s := v.(type) { +		case xml.StartElement: +			if s.Name == bind { +				return true +			} +		} +	} + +	return false +} + +func (s *session) sendBind() { +	iqStart := xml.StartElement{ +		xml.Name{"jabber:client", "iq"}, +		[]xml.Attr{ +			xml.Attr{xml.Name{"", "id"}, fmt.Sprintf("%016x", rand.Uint64())}, +			xml.Attr{xml.Name{"", "type"}, "set"}, +		}, +	} +	iqEnd := iqStart.End() + +	bindStart := xml.StartElement{ +		xml.Name{"urn:ietf:params:xml:ns:xmpp-bind", "bind"}, +		[]xml.Attr{}, +	} +	bindEnd := bindStart.End() + +	resourceStart := xml.StartElement{ +		xml.Name{"", "resource"}, +		[]xml.Attr{}, +	} +	resourceEnd := resourceStart.End() + +	name := xml.CharData("limox-" + fmt.Sprintf("%08x", rand.Uint32())) + +	tokens := [...]xml.Token{ +		iqStart, +		bindStart, +		resourceStart, +		name, +		resourceEnd, +		bindEnd, +		iqEnd, +	} + +	for _, v := range tokens { +		err := s.ed.encodeToken(v) +		if err != nil { +			log.Println("Could not encode ressource binding!") +			return +		} +	} +} diff --git a/xmpp/router.go b/xmpp/router.go index 9d69033..1d9c3e5 100644 --- a/xmpp/router.go +++ b/xmpp/router.go @@ -25,9 +25,17 @@ func getRoutingTable() routingTable {  		{xml.Name{`http://etherx.jabber.org/streams`, `features`}, streamFeaturesHandler},  		{xml.Name{`urn:ietf:params:xml:ns:xmpp-sasl`, `success`}, saslSuccessHandler},  		{xml.Name{`urn:ietf:params:xml:ns:xmpp-sasl`, `failure`}, saslFailureHandler}, +		{xml.Name{`jabber:client`, `iq`}, voidIq},  	}  } +// voidIq just logs that an IQ element was received. In the current state of +// the software there is no further processing. +// TODO process IQs for error handling and further information processing. +func voidIq(s *session, e []xml.Token) { +	log.Println("Received IQ element") +} +  // route determines the correct handler function for the given XML element by a  // given routingTable. In addition it executes the determined handler function.  // If no handler function is found an error message is send via the log module. diff --git a/xmpp/stream_pair.go b/xmpp/stream_pair.go index 693972e..4690f57 100644 --- a/xmpp/stream_pair.go +++ b/xmpp/stream_pair.go @@ -98,5 +98,10 @@ func streamFeaturesHandler(s *session, e []xml.Token) {  		return  	} +	if hasBind(e) { +		s.sendBind() +		return +	} +  	log.Println("Stream has no implemented features!")  }  | 
