[TASK] refactory component

This commit is contained in:
Martin/Geno 2019-06-01 04:38:35 +02:00
parent 709ce45e93
commit 32a646012c
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
9 changed files with 314 additions and 145 deletions

View File

@ -6,8 +6,6 @@ import (
"github.com/stretchr/testify/assert"
)
// correct run on root of this project
func TestServe(t *testing.T) {
assert := assert.New(t)

33
component/config.go Normal file
View File

@ -0,0 +1,33 @@
package component
import (
"gosrc.io/xmpp"
)
type Config struct {
Type string
Host string
Connection string
Secret string
Special map[string]interface{}
xmpp *xmpp.Component
comp Component
}
func (c *Config) Start() error {
c.xmpp = &xmpp.Component{Host: c.Host, Secret: c.Secret}
err := c.xmpp.Connect(c.Connection)
if err != nil {
return err
}
out, err := c.comp.Connect()
if err != nil {
return err
}
go c.sender(out)
go c.receiver()
return nil
}

19
component/config_test.go Normal file
View File

@ -0,0 +1,19 @@
package component
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestConfigStart(t *testing.T) {
assert := assert.New(t)
c := Config{}
// wrong connection
err := c.Start()
assert.NotNil(err)
// correct connection without xmpp server not possible
}

View File

@ -1 +1,25 @@
package component
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAddComponent(t *testing.T) {
assert := assert.New(t)
AddComponent("a", func(config map[string]interface{}) (Component, error) { return nil, nil })
assert.NotNil(components["a"])
assert.Len(components, 1)
}
func TestLoad(t *testing.T) {
AddComponent("a", func(config map[string]interface{}) (Component, error) { return nil, nil })
Load([]Config{
{},
// {Type: "a", Connection: "[::1]:10001"},
})
}

108
component/receiver.go Normal file
View File

@ -0,0 +1,108 @@
package component
import (
"github.com/bdlm/log"
"gosrc.io/xmpp"
)
func (c *Config) receiver() {
for {
packet, err := c.xmpp.ReadPacket()
if err != nil {
log.WithField("type", c.Type).Panicf("connection closed%s", err)
return
}
p, back := c.receive(packet)
if p == nil {
continue
}
if back {
c.xmpp.Send(p)
} else {
c.comp.Send(p)
}
}
}
func (c *Config) receive(packet xmpp.Packet) (xmpp.Packet, bool) {
logger := log.WithField("type", c.Type)
switch p := packet.(type) {
case xmpp.IQ:
attrs := p.PacketAttrs
loggerIQ := logger.WithFields(map[string]interface{}{
"from": attrs.From,
"to": attrs.To,
})
switch inner := p.Payload[0].(type) {
case *xmpp.DiscoInfo:
if p.Type == "get" {
iq := xmpp.NewIQ("result", attrs.To, attrs.From, attrs.Id, "en")
var identity xmpp.Identity
if inner.Node == "" {
identity = xmpp.Identity{
Name: c.Type,
Category: "gateway",
Type: "service",
}
}
payload := xmpp.DiscoInfo{
Identity: identity,
Features: []xmpp.Feature{
{Var: "http://jabber.org/protocol/disco#info"},
{Var: "http://jabber.org/protocol/disco#item"},
{Var: xmpp.NSSpaceXEP0184Receipt},
{Var: xmpp.NSSpaceXEP0333ChatMarkers},
},
}
iq.AddPayload(&payload)
loggerIQ.Debug("disco info")
return iq, true
}
case *xmpp.DiscoItems:
if p.Type == "get" {
iq := xmpp.NewIQ("result", attrs.To, attrs.From, attrs.Id, "en")
var payload xmpp.DiscoItems
if inner.Node == "" {
payload = xmpp.DiscoItems{
Items: []xmpp.DiscoItem{
{Name: c.Type, JID: c.Host, Node: "node1"},
},
}
}
iq.AddPayload(&payload)
loggerIQ.Debug("disco items")
return iq, true
}
default:
logger.Debug("ignoring iq packet", inner)
xError := xmpp.Err{
Code: 501,
Reason: "feature-not-implemented",
Type: "cancel",
}
reply := p.MakeError(xError)
return reply, true
}
case xmpp.Message:
logger.WithFields(map[string]interface{}{
"from": p.PacketAttrs.From,
"to": p.PacketAttrs.To,
"id": p.PacketAttrs.Id,
}).Debug(p.XMPPFormat())
return packet, false
case xmpp.Presence:
logger.Debug("received presence:", p.Type)
default:
logger.Debug("ignoring packet:", packet)
}
return nil, false
}

View File

@ -0,0 +1,65 @@
package component
import (
"testing"
"github.com/stretchr/testify/assert"
"gosrc.io/xmpp"
)
func TestReceive(t *testing.T) {
assert := assert.New(t)
c := Config{Host: "example.org", Type: "monkeyservice"}
// ignoring packet
p, back := c.receive(xmpp.Handshake{})
assert.Nil(p)
// receive presence
p, back = c.receive(xmpp.Presence{})
assert.Nil(p)
// message
p, back = c.receive(xmpp.Message{})
assert.False(back)
assert.NotNil(p)
// unsupported iq
p, back = c.receive(xmpp.IQ{Payload: []xmpp.IQPayload{
&xmpp.Err{},
}})
assert.True(back)
assert.NotNil(p)
iq := p.(xmpp.IQ)
assert.Equal("error", iq.Type)
assert.Equal("feature-not-implemented", iq.Error.Reason)
// iq disco info
p, back = c.receive(xmpp.IQ{
PacketAttrs: xmpp.PacketAttrs{Type: "get"},
Payload: []xmpp.IQPayload{
&xmpp.DiscoInfo{},
},
})
assert.True(back)
assert.NotNil(p)
iq = p.(xmpp.IQ)
assert.Equal("result", iq.Type)
dinfo := iq.Payload[0].(*xmpp.DiscoInfo)
assert.Equal("monkeyservice", dinfo.Identity.Name)
// iq disco items
p, back = c.receive(xmpp.IQ{
PacketAttrs: xmpp.PacketAttrs{Type: "get"},
Payload: []xmpp.IQPayload{
&xmpp.DiscoItems{},
},
})
assert.True(back)
assert.NotNil(p)
iq = p.(xmpp.IQ)
assert.Equal("result", iq.Type)
ditems := iq.Payload[0].(*xmpp.DiscoItems)
assert.Equal("monkeyservice", ditems.Items[0].Name)
}

35
component/send.go Normal file
View File

@ -0,0 +1,35 @@
package component
import (
"github.com/bdlm/log"
"gosrc.io/xmpp"
)
func (c *Config) sender(packets chan xmpp.Packet) {
for packet := range packets {
if p := c.send(packet); p != nil {
c.xmpp.Send(p)
}
}
}
func (c *Config) send(packet xmpp.Packet) xmpp.Packet {
logger := log.WithField("type", c.Type)
switch p := packet.(type) {
case xmpp.Message:
if p.PacketAttrs.From == "" {
p.PacketAttrs.From = c.Host
} else {
p.PacketAttrs.From += "@" + c.Host
}
logger.WithFields(map[string]interface{}{
"from": p.PacketAttrs.From,
"to": p.PacketAttrs.To,
"id": p.PacketAttrs.Id,
}).Debug(p.XMPPFormat())
return p
default:
log.Warn("ignoring packet:", packet)
return nil
}
}

30
component/send_test.go Normal file
View File

@ -0,0 +1,30 @@
package component
import (
"testing"
"github.com/stretchr/testify/assert"
"gosrc.io/xmpp"
)
func TestSend(t *testing.T) {
assert := assert.New(t)
c := Config{Host: "example.org"}
// ignoring packet
p := c.send(xmpp.IQ{})
assert.Nil(p)
// send by component host
p = c.send(xmpp.Message{})
assert.NotNil(p)
msg := p.(xmpp.Message)
assert.Equal("example.org", msg.PacketAttrs.From)
// send by a user of component
p = c.send(xmpp.Message{PacketAttrs: xmpp.PacketAttrs{From: "threemaid"}})
assert.NotNil(p)
msg = p.(xmpp.Message)
assert.Equal("threemaid@example.org", msg.PacketAttrs.From)
}

View File

@ -1,143 +0,0 @@
package component
import (
"github.com/bdlm/log"
"gosrc.io/xmpp"
)
type Config struct {
Type string
Host string
Connection string
Secret string
Special map[string]interface{}
xmpp *xmpp.Component
comp Component
}
func (c *Config) Start() error {
c.xmpp = &xmpp.Component{Host: c.Host, Secret: c.Secret}
err := c.xmpp.Connect(c.Connection)
if err != nil {
return err
}
out, err := c.comp.Connect()
if err != nil {
return err
}
go c.recieve(out)
go c.sender()
return nil
}
func (c *Config) recieve(packets chan xmpp.Packet) {
logger := log.WithField("type", c.Type)
for packet := range packets {
switch p := packet.(type) {
case xmpp.Message:
if p.PacketAttrs.From == "" {
p.PacketAttrs.From = c.Host
} else {
p.PacketAttrs.From += "@" + c.Host
}
logger.WithFields(map[string]interface{}{
"from": p.PacketAttrs.From,
"to": p.PacketAttrs.To,
"id": p.PacketAttrs.Id,
}).Debug(p.XMPPFormat())
c.xmpp.Send(p)
default:
log.Warn("ignoring packet:", packet)
}
}
}
func (c *Config) sender() {
logger := log.WithField("type", c.Type)
for {
packet, err := c.xmpp.ReadPacket()
if err != nil {
logger.Panicf("connection closed%s", err)
return
}
switch p := packet.(type) {
case xmpp.IQ:
attrs := p.PacketAttrs
loggerIQ := logger.WithFields(map[string]interface{}{
"from": attrs.From,
"to": attrs.To,
})
switch inner := p.Payload[0].(type) {
case *xmpp.DiscoInfo:
loggerIQ.Debug("Disco Info")
if p.Type == "get" {
iq := xmpp.NewIQ("result", attrs.To, attrs.From, attrs.Id, "en")
var identity xmpp.Identity
if inner.Node == "" {
identity = xmpp.Identity{
Name: c.Type,
Category: "gateway",
Type: "service",
}
}
payload := xmpp.DiscoInfo{
Identity: identity,
Features: []xmpp.Feature{
{Var: "http://jabber.org/protocol/disco#info"},
{Var: "http://jabber.org/protocol/disco#item"},
{Var: xmpp.NSSpaceXEP0184Receipt},
{Var: xmpp.NSSpaceXEP0333ChatMarkers},
},
}
iq.AddPayload(&payload)
_ = c.xmpp.Send(iq)
}
case *xmpp.DiscoItems:
loggerIQ.Debug("DiscoItems")
if p.Type == "get" {
iq := xmpp.NewIQ("result", attrs.To, attrs.From, attrs.Id, "en")
var payload xmpp.DiscoItems
if inner.Node == "" {
payload = xmpp.DiscoItems{
Items: []xmpp.DiscoItem{
{Name: c.Type, JID: c.Host, Node: "node1"},
},
}
}
iq.AddPayload(&payload)
_ = c.xmpp.Send(iq)
}
default:
logger.Debug("ignoring iq packet", inner)
xError := xmpp.Err{
Code: 501,
Reason: "feature-not-implemented",
Type: "cancel",
}
reply := p.MakeError(xError)
_ = c.xmpp.Send(&reply)
}
case xmpp.Message:
logger.WithFields(map[string]interface{}{
"from": p.PacketAttrs.From,
"to": p.PacketAttrs.To,
"id": p.PacketAttrs.Id,
}).Debug(p.XMPPFormat())
c.comp.Send(packet)
case xmpp.Presence:
logger.Debug("Received presence:", p.Type)
default:
logger.Debug("ignoring packet:", packet)
}
}
}