Unverified Commit 40e80111 authored by Ola Bini's avatar Ola Bini

Refactor implementation a bit

parent 94eb489a
package main
func appendShort(l []byte, r uint16) []byte {
return append(l, byte(r>>8), byte(r))
}
func extractShort(d []byte) ([]byte, uint16, bool) {
if len(d) < 2 {
return nil, 0, false
}
return d[2:], uint16(d[0])<<8 |
uint16(d[1]), true
}
package main
import "encoding/xml"
// DiscoveryInfoQuery contains the deserialized information about a service discovery info query
// See: XEP-0030, Section 3
type DiscoveryInfoQuery struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"`
Node string `xml:"node,omitempty"`
Identities []DiscoveryIdentity `xml:"identity,omitempty"`
Features []DiscoveryFeature `xml:"feature,omitempty"`
}
// DiscoveryIdentity contains identity information for a specific discovery
type DiscoveryIdentity struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info identity"`
Lang string `xml:"lang,attr,omitempty"`
Category string `xml:"category,attr"`
Type string `xml:"type,attr"`
Name string `xml:"name,attr"`
}
// DiscoveryFeature contains information about a specific discovery feature
type DiscoveryFeature struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info feature"`
Var string `xml:"var,attr"`
}
// DiscoveryItemsQuery contains a query for discovery items
type DiscoveryItemsQuery struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items query"`
DiscoveryItems []DiscoveryItem `xml:"item,omitempty"`
}
// DiscoveryItem contains one discovery item
type DiscoveryItem struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items item"`
Jid string `xml:"jid,attr"`
Name string `xml:"name,attr"`
Node string `xml:"node, attr"`
}
package main
import (
"fmt"
xco "github.com/sheenobu/go-xco"
)
func unknownIQ(stanza *xco.Iq) (ret interface{}, iqtype string, ignore bool) {
fmt.Printf("Unknown IQ: %s\n", stanza.Content)
return nil, "", false
}
type iqFunction func(*xco.Iq) (interface{}, string, bool)
var knownIQs = map[string]iqFunction{}
func registerKnownIQ(stanzaType, fullName string, f iqFunction) {
knownIQs[stanzaType+" "+fullName] = f
}
func getIQHandler(stanzaType, namespace, local string) iqFunction {
f, ok := knownIQs[fmt.Sprintf("%s %s %s", stanzaType, namespace, local)]
if ok {
return f
}
return unknownIQ
}
func processIQ(stanza *xco.Iq) (ret interface{}, iqtype string, ignore bool) {
if nspace, local, ok := tryDecodeXML([]byte(stanza.Content)); ok {
return getIQHandler(stanza.Type, nspace, local)(stanza)
}
return nil, "", false
}
func discoInfoIQ(_ *xco.Iq) (interface{}, string, bool) {
return DiscoveryInfoQuery{
Identities: []DiscoveryIdentity{
{
Category: "auth",
Type: "otr-prekey",
Name: "OTR Prekey Server",
},
},
Features: []DiscoveryFeature{
{Var: "http://jabber.org/protocol/disco#info"},
{Var: "http://jabber.org/protocol/disco#items"},
{Var: "http://jabber.org/protocol/otrv4-prekey-server"},
},
}, "", false
}
func discoItemsIQ(_ *xco.Iq) (interface{}, string, bool) {
return DiscoveryItemsQuery{
DiscoveryItems: []DiscoveryItem{
{
Jid: *xmppName,
Node: "fingerprint",
Name: *prekeyServerFingerprint,
},
},
}, "", false
}
func init() {
registerKnownIQ("get", "http://jabber.org/protocol/disco#info query", discoInfoIQ)
registerKnownIQ("get", "http://jabber.org/protocol/disco#items query", discoItemsIQ)
}
package main
import (
"bytes"
"encoding/xml"
"flag"
"fmt"
"io/ioutil"
......@@ -13,14 +11,20 @@ import (
func main() {
flag.Parse()
// TODO: validate fingerprint
// TODO: validate xmppName
// TODO: validate shared secret
opts := xco.Options{
Name: *xmppName,
SharedSecret: *xmppSharedSecret,
Address: net.JoinHostPort(*xmppIP, fmt.Sprintf("%d", *xmppPort)),
Address: joinHostPort(*xmppIP, *xmppPort),
}
c, err := xco.NewComponent(opts)
if err != nil {
// TODO: print error properly
panic(err)
}
......@@ -38,12 +42,14 @@ func main() {
}
c.Send(&resp)
// TODO: print error properly
return nil
}
c.IqHandler = func(_ *xco.Component, m *xco.Iq) error {
ret, _, _ := processIQ(m)
// TODO: print error properly
resp := xco.Iq{
Header: xco.Header{
From: m.To,
......@@ -56,152 +62,31 @@ func main() {
}
c.Send(&resp)
// TODO: print error properly
return nil
}
e := c.Run()
if e != nil {
// TODO: print error properly
panic(e)
}
}
func xmlToString(x interface{}) string {
enc, _ := xml.Marshal(x)
return string(enc)
}
func unknownIQ(stanza *xco.Iq) (ret interface{}, iqtype string, ignore bool) {
fmt.Printf("Unknown IQ: %s\n", stanza.Content)
return nil, "", false
}
type iqFunction func(*xco.Iq) (interface{}, string, bool)
var knownIQs = map[string]iqFunction{}
func registerKnownIQ(stanzaType, fullName string, f iqFunction) {
knownIQs[stanzaType+" "+fullName] = f
}
func getIQHandler(stanzaType, namespace, local string) iqFunction {
f, ok := knownIQs[fmt.Sprintf("%s %s %s", stanzaType, namespace, local)]
if ok {
return f
}
return unknownIQ
}
func processIQ(stanza *xco.Iq) (ret interface{}, iqtype string, ignore bool) {
if nspace, local, ok := tryDecodeXML([]byte(stanza.Content)); ok {
return getIQHandler(stanza.Type, nspace, local)(stanza)
}
return nil, "", false
func joinHostPort(ip string, port uint) string {
return net.JoinHostPort(ip, fmt.Sprintf("%d", port))
}
func tryDecodeXML(data []byte) (nspace, local string, ok bool) {
token, _ := xml.NewDecoder(bytes.NewBuffer(data)).Token()
if token == nil {
return "", "", false
}
startElem, ok := token.(xml.StartElement)
if !ok {
return "", "", false
}
return startElem.Name.Space, startElem.Name.Local, true
}
func discoInfoIQ(_ *xco.Iq) (interface{}, string, bool) {
return DiscoveryInfoQuery{
Identities: []DiscoveryIdentity{
{
Category: "auth",
Type: "otr-prekey",
Name: "OTR Prekey Server",
},
},
Features: []DiscoveryFeature{
{Var: "http://jabber.org/protocol/disco#info"},
{Var: "http://jabber.org/protocol/disco#items"},
{Var: "http://jabber.org/protocol/otrv4-prekey-server"},
},
}, "", false
}
func discoItemsIQ(_ *xco.Iq) (interface{}, string, bool) {
return DiscoveryItemsQuery{
DiscoveryItems: []DiscoveryItem{
{
Jid: *xmppName,
Node: "fingerprint",
Name: *prekeyServerFingerprint,
},
},
}, "", false
}
func init() {
registerKnownIQ("get", "http://jabber.org/protocol/disco#info query", discoInfoIQ)
registerKnownIQ("get", "http://jabber.org/protocol/disco#items query", discoItemsIQ)
}
// DiscoveryInfoQuery contains the deserialized information about a service discovery info query
// See: XEP-0030, Section 3
type DiscoveryInfoQuery struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"`
Node string `xml:"node,omitempty"`
Identities []DiscoveryIdentity `xml:"identity,omitempty"`
Features []DiscoveryFeature `xml:"feature,omitempty"`
}
// DiscoveryIdentity contains identity information for a specific discovery
type DiscoveryIdentity struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info identity"`
Lang string `xml:"lang,attr,omitempty"`
Category string `xml:"category,attr"`
Type string `xml:"type,attr"`
Name string `xml:"name,attr"`
}
// DiscoveryFeature contains information about a specific discovery feature
type DiscoveryFeature struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info feature"`
Var string `xml:"var,attr"`
}
// DiscoveryItemsQuery contains a query for discovery items
type DiscoveryItemsQuery struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items query"`
DiscoveryItems []DiscoveryItem `xml:"item,omitempty"`
}
// DiscoveryItem contains one discovery item
type DiscoveryItem struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items item"`
Jid string `xml:"jid,attr"`
Name string `xml:"name,attr"`
Node string `xml:"node, attr"`
}
func appendShort(l []byte, r uint16) []byte {
return append(l, byte(r>>8), byte(r))
}
func extractShort(d []byte) ([]byte, uint16, bool) {
if len(d) < 2 {
return nil, 0, false
}
return d[2:], uint16(d[0])<<8 |
uint16(d[1]), true
func getTCPAddr(ip string, port uint) *net.TCPAddr {
addr, _ := net.ResolveTCPAddr("tcp", joinHostPort(ip, port))
return addr
}
func getPrekeyResponseFromRealServer(u string, data []byte) []byte {
addr, _ := net.ResolveTCPAddr("tcp", net.JoinHostPort(*rawIP, fmt.Sprintf("%d", *rawPort)))
addr := getTCPAddr(*rawIP, *rawPort)
con, _ := net.DialTCP(addr.Network(), nil, addr)
// TODO: print error properly
defer con.Close()
toSend := []byte{}
......@@ -210,8 +95,10 @@ func getPrekeyResponseFromRealServer(u string, data []byte) []byte {
toSend = appendShort(toSend, uint16(len(data)))
toSend = append(toSend, data...)
con.Write(toSend)
// TODO: print error properly
con.CloseWrite()
res, _ := ioutil.ReadAll(con)
// TODO: print error properly
res2, ss, _ := extractShort(res)
if uint16(len(res2)) != ss {
fmt.Printf("Unexpected length of data received\n")
......
package main
import (
"bytes"
"encoding/xml"
)
func xmlToString(x interface{}) string {
enc, _ := xml.Marshal(x)
return string(enc)
}
func tryDecodeXML(data []byte) (nspace, local string, ok bool) {
token, _ := xml.NewDecoder(bytes.NewBuffer(data)).Token()
if token == nil {
return "", "", false
}
startElem, ok := token.(xml.StartElement)
if !ok {
return "", "", false
}
return startElem.Name.Space, startElem.Name.Local, true
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment