1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package xmpp
import (
"encoding/xml"
"log"
)
// routingTable is a data structure which contains routing information for XML
// elements. The xml.StartElement at the beginning of an XML element has a name
// containing the XML namespace and a local name. Based on this compisition
// which forms the xml.Name the appropriate handler function is defined by each
// entry of the routingTable.
type routingTable []struct {
name xml.Name
handler func(*session, []xml.Token)
}
// getRoutingTable returns the routing table used in
// xengineering.eu/limox/xmpp. Since Go does not allow such a datatype as a
// constant such a function is a simple yet inefficient approach to guarantee
// that an unmodified routing table is delivered to each user. A global
// variable would have the problem that it could be altered during execution.
func getRoutingTable() routingTable {
return 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`}, iqHandler},
}
}
// 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.
func route(s *session, e []xml.Token, t routingTable) {
var name xml.Name
// TODO a stronger definition of an XML element (as here
// https://www.w3schools.com/xml/xml_elements.asp) would define that the
// first Token of an element is a StartElement token. This would make this
// code easier.
escape := false
for _, token := range e {
switch s := token.(type) {
case xml.StartElement:
name = s.Name
escape = true
}
if escape {
break
}
}
for _, r := range t {
if name == r.name {
r.handler(s, e)
return
}
}
log.Println("Could not route XML element")
}
|