Adhoc test component can successfully connect to ejabberd
This commit is contained in:
parent
b31c29a03d
commit
90865aeb8e
36
component.go
36
component.go
|
@ -1,6 +1,8 @@
|
||||||
package xmpp
|
package xmpp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -15,17 +17,41 @@ const componentStreamOpen = "<?xml version='1.0'?><stream:stream to='%s' xmlns='
|
||||||
// using external components. Component specifications are defined
|
// using external components. Component specifications are defined
|
||||||
// in XEP-0114, XEP-0355 and XEP-0356.
|
// in XEP-0114, XEP-0355 and XEP-0356.
|
||||||
type Component struct {
|
type Component struct {
|
||||||
|
Host string
|
||||||
|
Secret string
|
||||||
|
|
||||||
// TCP level connection
|
// TCP level connection
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
|
|
||||||
// read / write
|
// read / write
|
||||||
socketProxy io.ReadWriter
|
socketProxy io.ReadWriter // TODO
|
||||||
decoder *xml.Decoder
|
decoder *xml.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Handshake struct {
|
||||||
|
XMLName xml.Name `xml:"jabber:component:accept handshake"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handshake generates an authentication token based on StreamID and shared secret.
|
||||||
|
func (c *Component) Handshake(streamId string) string {
|
||||||
|
// 1. Concatenate the Stream ID received from the server with the shared secret.
|
||||||
|
concatStr := streamId + c.Secret
|
||||||
|
|
||||||
|
// 2. Hash the concatenated string according to the SHA1 algorithm, i.e., SHA1( concat (sid, password)).
|
||||||
|
h := sha1.New()
|
||||||
|
h.Write([]byte(concatStr))
|
||||||
|
hash := h.Sum(nil)
|
||||||
|
|
||||||
|
// 3. Ensure that the hash output is in hexadecimal format, not binary or base64.
|
||||||
|
// 4. Convert the hash output to all lowercase characters.
|
||||||
|
encodedStr := hex.EncodeToString(hash)
|
||||||
|
|
||||||
|
return encodedStr
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Helper to prepare connection string
|
// TODO Helper to prepare connection string
|
||||||
func Open(connStr string) error {
|
func Open(connStr string) error {
|
||||||
c := Component{}
|
c := Component{Host: connStr, Secret: "mypass"}
|
||||||
|
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
var err error
|
var err error
|
||||||
|
@ -36,7 +62,7 @@ func Open(connStr string) error {
|
||||||
|
|
||||||
// TODO send stream open and check for reply
|
// TODO send stream open and check for reply
|
||||||
// Send stream open tag
|
// Send stream open tag
|
||||||
componentHost := connStr // TODO Fix me
|
componentHost := connStr // TODO Fix me: Extract componentID + secret
|
||||||
if _, err := fmt.Fprintf(conn, componentStreamOpen, componentHost, NSComponent, NSStream); err != nil {
|
if _, err := fmt.Fprintf(conn, componentStreamOpen, componentHost, NSComponent, NSStream); err != nil {
|
||||||
fmt.Println("cannot send stream open.")
|
fmt.Println("cannot send stream open.")
|
||||||
return err
|
return err
|
||||||
|
@ -53,7 +79,7 @@ func Open(connStr string) error {
|
||||||
fmt.Println("StreamID = ", streamId)
|
fmt.Println("StreamID = ", streamId)
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
if _, err := fmt.Fprint(conn, "<handshake>aaee83c26aeeafcbabeabfcbcd50df997e0a2a1e</handshake>"); err != nil {
|
if _, err := fmt.Fprintf(conn, "<handshake>%s</handshake>", c.Handshake(streamId)); err != nil {
|
||||||
fmt.Println("cannot send stream open.")
|
fmt.Println("cannot send stream open.")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -68,6 +94,8 @@ func Open(connStr string) error {
|
||||||
switch v := val.(type) {
|
switch v := val.(type) {
|
||||||
case *StreamError:
|
case *StreamError:
|
||||||
fmt.Printf("error: %s", v.Error.Local)
|
fmt.Printf("error: %s", v.Error.Local)
|
||||||
|
case *Handshake:
|
||||||
|
fmt.Println("Component connected")
|
||||||
default:
|
default:
|
||||||
return errors.New("unexpected packet, got " + name.Local + " in " + name.Space)
|
return errors.New("unexpected packet, got " + name.Local + " in " + name.Space)
|
||||||
}
|
}
|
||||||
|
|
18
component_test.go
Normal file
18
component_test.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package xmpp
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestHandshake(t *testing.T) {
|
||||||
|
c := Component{
|
||||||
|
Host: "test.localhost",
|
||||||
|
Secret: "mypass",
|
||||||
|
}
|
||||||
|
|
||||||
|
streamID := "1263952298440005243"
|
||||||
|
expected := "c77e2ef0109fbbc5161e83b51629cd1353495332"
|
||||||
|
|
||||||
|
result := c.Handshake(streamID)
|
||||||
|
if result != expected {
|
||||||
|
t.Errorf("incorrect handshake calculation '%s' != '%s'", result, expected)
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,6 +86,8 @@ func next(p *xml.Decoder) (xml.Name, interface{}, error) {
|
||||||
nv = &ClientPresence{}
|
nv = &ClientPresence{}
|
||||||
case NSClient + " iq":
|
case NSClient + " iq":
|
||||||
nv = &ClientIQ{}
|
nv = &ClientIQ{}
|
||||||
|
case NSComponent + " handshake":
|
||||||
|
nv = &Handshake{}
|
||||||
default:
|
default:
|
||||||
return xml.Name{}, nil, errors.New("unexpected XMPP message " +
|
return xml.Name{}, nil, errors.New("unexpected XMPP message " +
|
||||||
se.Name.Space + " <" + se.Name.Local + "/>")
|
se.Name.Space + " <" + se.Name.Local + "/>")
|
||||||
|
|
Loading…
Reference in a new issue