sum7
/
yaja
Archived
1
0
Fork 0

add client logging + improve logging

This commit is contained in:
Martin/Geno 2018-02-11 22:03:58 +01:00
parent 654d0306cf
commit 3c13b83657
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
11 changed files with 289 additions and 161 deletions

View File

@ -22,6 +22,7 @@ func (client *Client) auth(password string) error {
challenge := &messages.SASLChallenge{} challenge := &messages.SASLChallenge{}
response := &messages.SASLResponse{} response := &messages.SASLResponse{}
for _, m := range f.Mechanisms.Mechanism { for _, m := range f.Mechanisms.Mechanism {
client.Logging.Debugf("try auth with '%s'", m)
if m == "SCRAM-SHA-1" { if m == "SCRAM-SHA-1" {
/* /*
mechanism = m mechanism = m
@ -33,10 +34,10 @@ func (client *Client) auth(password string) error {
if m == "DIGEST-MD5" { if m == "DIGEST-MD5" {
mechanism = m mechanism = m
// Digest-MD5 authentication // Digest-MD5 authentication
client.Out.Encode(&messages.SASLAuth{ client.Send(&messages.SASLAuth{
Mechanism: m, Mechanism: m,
}) })
if err := client.ReadElement(challenge); err != nil { if err := client.ReadDecode(challenge); err != nil {
return err return err
} }
b, err := base64.StdEncoding.DecodeString(challenge.Body) b, err := base64.StdEncoding.DecodeString(challenge.Body)
@ -65,7 +66,7 @@ func (client *Client) auth(password string) error {
"\", nc=" + nonceCount + ", qop=" + qop + ", digest-uri=\"" + digestURI + "\", response=" + digest + ", charset=" + charset "\", nc=" + nonceCount + ", qop=" + qop + ", digest-uri=\"" + digestURI + "\", response=" + digest + ", charset=" + charset
response.Body = base64.StdEncoding.EncodeToString([]byte(message)) response.Body = base64.StdEncoding.EncodeToString([]byte(message))
client.Out.Encode(response) client.Send(response)
break break
} }
if m == "PLAIN" { if m == "PLAIN" {
@ -74,7 +75,7 @@ func (client *Client) auth(password string) error {
raw := "\x00" + client.JID.Local + "\x00" + password raw := "\x00" + client.JID.Local + "\x00" + password
enc := make([]byte, base64.StdEncoding.EncodedLen(len(raw))) enc := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
base64.StdEncoding.Encode(enc, []byte(raw)) base64.StdEncoding.Encode(enc, []byte(raw))
client.Out.Encode(&messages.SASLAuth{ client.Send(&messages.SASLAuth{
Mechanism: "PLAIN", Mechanism: "PLAIN",
Body: string(enc), Body: string(enc),
}) })
@ -85,15 +86,17 @@ func (client *Client) auth(password string) error {
if mechanism == "" { if mechanism == "" {
return fmt.Errorf("PLAIN authentication is not an option: %s", f.Mechanisms.Mechanism) return fmt.Errorf("PLAIN authentication is not an option: %s", f.Mechanisms.Mechanism)
} }
client.Logging.Info("used auth with '%s'", mechanism)
element, err := client.Read() element, err := client.Read()
if err != nil { if err != nil {
return err return err
} }
fail := messages.SASLFailure{} fail := messages.SASLFailure{}
if err := client.In.DecodeElement(&fail, element); err == nil { if err := client.Decode(&fail, element); err == nil {
return errors.New(messages.XMLChildrenString(fail) + " : " + fail.Body) return errors.New(messages.XMLChildrenString(fail) + " : " + fail.Body)
} }
if err := client.In.DecodeElement(&messages.SASLSuccess{}, element); err != nil { if err := client.Decode(&messages.SASLSuccess{}, element); err != nil {
return errors.New("auth failed - with unexpected answer") return errors.New("auth failed - with unexpected answer")
} }
return nil return nil

View File

@ -3,32 +3,41 @@ package client
import ( import (
"crypto/tls" "crypto/tls"
"encoding/xml" "encoding/xml"
"errors"
"fmt" "fmt"
"net" "net"
"strings" "strings"
"time" "time"
"dev.sum7.eu/genofire/yaja/messages" log "github.com/sirupsen/logrus"
"dev.sum7.eu/genofire/yaja/model" "dev.sum7.eu/genofire/yaja/model"
) )
// Client holds XMPP connection opitons // Client holds XMPP connection opitons
type Client struct { type Client struct {
conn net.Conn // connection to server Protocol string // tcp tcp4 tcp6 are supported
Out *xml.Encoder Timeout time.Duration
In *xml.Decoder conn net.Conn // connection to server
out *xml.Encoder
in *xml.Decoder
Logging *log.Logger
JID *model.JID JID *model.JID
} }
func NewClient(jid *model.JID, password string) (*Client, error) { func NewClient(jid *model.JID, password string) (*Client, error) {
return NewClientProtocolDuration(jid, password, "tcp", 0) client := &Client{
} Protocol: "tcp",
JID: jid,
Logging: log.New(),
}
return client, client.Connect(password)
func NewClientProtocolDuration(jid *model.JID, password string, proto string, timeout time.Duration) (*Client, error) { }
_, srvEntries, err := net.LookupSRV("xmpp-client", "tcp", jid.Domain) func (client *Client) Connect(password string) error {
addr := jid.Domain + ":5222" _, srvEntries, err := net.LookupSRV("xmpp-client", "tcp", client.JID.Domain)
addr := client.JID.Domain + ":5222"
if err == nil && len(srvEntries) > 0 { if err == nil && len(srvEntries) > 0 {
bestSrv := srvEntries[0] bestSrv := srvEntries[0]
for _, srv := range srvEntries { for _, srv := range srvEntries {
@ -42,23 +51,20 @@ func NewClientProtocolDuration(jid *model.JID, password string, proto string, ti
if len(a) == 1 { if len(a) == 1 {
addr += ":5222" addr += ":5222"
} }
conn, err := net.DialTimeout(proto, addr, timeout) if client.Protocol == "" {
if err != nil { client.Protocol = "tcp"
return nil, err
} }
client := &Client{ conn, err := net.DialTimeout(client.Protocol, addr, client.Timeout)
conn: conn, client.setConnection(conn)
In: xml.NewDecoder(conn), if err != nil {
Out: xml.NewEncoder(conn), return err
JID: jid,
} }
if err = client.connect(password); err != nil { if err = client.connect(password); err != nil {
client.Close() client.Close()
return nil, err return err
} }
return client, nil return nil
} }
// Close closes the XMPP connection // Close closes the XMPP connection
@ -68,94 +74,3 @@ func (c *Client) Close() error {
} }
return nil return nil
} }
func (client *Client) startStream() (*messages.StreamFeatures, error) {
// XMPP-Connection
_, err := fmt.Fprintf(client.conn, "<?xml version='1.0'?>\n"+
"<stream:stream to='%s' xmlns='%s'\n"+
" xmlns:stream='%s' version='1.0'>\n",
model.XMLEscape(client.JID.Domain), messages.NSClient, messages.NSStream)
if err != nil {
return nil, err
}
element, err := client.Read()
if err != nil {
return nil, err
}
if element.Name.Space != messages.NSStream || element.Name.Local != "stream" {
return nil, errors.New("is not stream")
}
f := &messages.StreamFeatures{}
if err := client.ReadElement(f); err != nil {
return nil, err
}
return f, nil
}
func (client *Client) connect(password string) error {
if _, err := client.startStream(); err != nil {
return err
}
if err := client.Out.Encode(&messages.TLSStartTLS{}); err != nil {
return err
}
var p messages.TLSProceed
if err := client.ReadElement(&p); err != nil {
return err
}
// Change tcp to tls
tlsconn := tls.Client(client.conn, &tls.Config{
ServerName: client.JID.Domain,
})
client.conn = tlsconn
client.In = xml.NewDecoder(client.conn)
client.Out = xml.NewEncoder(client.conn)
if err := tlsconn.Handshake(); err != nil {
return err
}
if err := tlsconn.VerifyHostname(client.JID.Domain); err != nil {
return err
}
if err := client.auth(password); err != nil {
return err
}
if _, err := client.startStream(); err != nil {
return err
}
// bind to resource
bind := &messages.Bind{}
if client.JID.Resource != "" {
bind.Resource = client.JID.Resource
}
if err := client.Out.Encode(&messages.IQClient{
Type: messages.IQTypeSet,
From: client.JID,
To: model.NewJID(client.JID.Domain),
Bind: bind,
}); err != nil {
return err
}
var iq messages.IQClient
if err := client.ReadElement(&iq); err != nil {
return err
}
if iq.Error != nil {
if iq.Error.ServiceUnavailable == nil {
return errors.New(fmt.Sprintf("recv error on iq>bind: %s[%s]: %s -> %s -> %s", iq.Error.Code, iq.Error.Type, iq.Error.Text, messages.XMLChildrenString(iq.Error.StanzaErrorGroup), messages.XMLChildrenString(iq.Error.Other)))
}
} else if iq.Bind == nil {
return errors.New("<iq> result missing <bind>")
} else if iq.Bind.JID != nil {
client.JID.Local = iq.Bind.JID.Local
client.JID.Domain = iq.Bind.JID.Domain
client.JID.Resource = iq.Bind.JID.Resource
} else {
return errors.New(messages.XMLChildrenString(iq.Other))
}
// set status
return client.Send(&messages.PresenceClient{Show: messages.PresenceShowXA, Status: "online"})
}

View File

@ -2,26 +2,34 @@ package client
import ( import (
"encoding/xml" "encoding/xml"
"log"
"dev.sum7.eu/genofire/yaja/messages" "dev.sum7.eu/genofire/yaja/messages"
) )
func (client *Client) Read() (*xml.StartElement, error) { func (client *Client) Read() (*xml.StartElement, error) {
for { for {
nextToken, err := client.In.Token() nextToken, err := client.in.Token()
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch nextToken.(type) { switch nextToken.(type) {
case xml.StartElement: case xml.StartElement:
element := nextToken.(xml.StartElement) element := nextToken.(xml.StartElement)
client.Logging.Debug("recv xml: ", messages.XMLStartElementToString(&element))
return &element, nil return &element, nil
} }
} }
} }
func (client *Client) Decode(p interface{}, element *xml.StartElement) error {
func (client *Client) ReadElement(p interface{}) error { err := client.in.DecodeElement(p, element)
if err != nil {
client.Logging.Debugf("decode failed xml: %s to: %v", messages.XMLStartElementToString(element), p)
} else {
client.Logging.Debugf("decode xml: %s to: %v with children %s", messages.XMLStartElementToString(element), p, messages.XMLChildrenString(p))
}
return err
}
func (client *Client) ReadDecode(p interface{}) error {
element, err := client.Read() element, err := client.Read()
if err != nil { if err != nil {
return err return err
@ -31,36 +39,45 @@ func (client *Client) ReadElement(p interface{}) error {
if !ok { if !ok {
iq = &messages.IQClient{} iq = &messages.IQClient{}
} }
err = client.In.DecodeElement(iq, element) err = client.Decode(iq, element)
if err == nil && iq.Ping != nil { if err == nil && iq.Ping != nil {
log.Println("answer ping") client.Logging.Info("ReadElement: auto answer ping")
iq.Type = messages.IQTypeResult iq.Type = messages.IQTypeResult
iq.To = iq.From iq.To = iq.From
iq.From = client.JID iq.From = client.JID
client.Out.Encode(iq) client.Send(iq)
return nil return nil
} }
if ok { if ok {
return err return err
} }
return client.In.DecodeElement(p, element) return client.Decode(p, element)
}
func (client *Client) encode(p interface{}) error {
err := client.out.Encode(p)
if err != nil {
client.Logging.Debugf("encode failed %v", p)
} else {
client.Logging.Debugf("encode %v with children %s", p, messages.XMLChildrenString(p))
}
return err
} }
func (client *Client) Send(p interface{}) error { func (client *Client) Send(p interface{}) error {
msg, ok := p.(*messages.MessageClient) msg, ok := p.(*messages.MessageClient)
if ok { if ok {
msg.From = client.JID msg.From = client.JID
return client.Out.Encode(msg) return client.encode(msg)
} }
iq, ok := p.(*messages.IQClient) iq, ok := p.(*messages.IQClient)
if ok { if ok {
iq.From = client.JID iq.From = client.JID
return client.Out.Encode(iq) return client.encode(iq)
} }
pc, ok := p.(*messages.PresenceClient) pc, ok := p.(*messages.PresenceClient)
if ok { if ok {
pc.From = client.JID pc.From = client.JID
return client.Out.Encode(pc) return client.encode(pc)
} }
return client.Out.Encode(p) return client.encode(p)
} }

122
client/connect.go Normal file
View File

@ -0,0 +1,122 @@
package client
import (
"crypto/tls"
"encoding/xml"
"errors"
"fmt"
"net"
"dev.sum7.eu/genofire/yaja/messages"
"dev.sum7.eu/genofire/yaja/model"
)
func (client *Client) setConnection(conn net.Conn) {
client.conn = conn
client.in = xml.NewDecoder(client.conn)
client.out = xml.NewEncoder(client.conn)
}
func (client *Client) startStream() (*messages.StreamFeatures, error) {
// XMPP-Connection
_, err := fmt.Fprintf(client.conn, "<?xml version='1.0'?>\n"+
"<stream:stream to='%s' xmlns='%s'\n"+
" xmlns:stream='%s' version='1.0'>\n",
model.XMLEscape(client.JID.Domain), messages.NSClient, messages.NSStream)
if err != nil {
return nil, err
}
element, err := client.Read()
if err != nil {
return nil, err
}
if element.Name.Space != messages.NSStream || element.Name.Local != "stream" {
return nil, errors.New("is not stream")
}
f := &messages.StreamFeatures{}
if err := client.ReadDecode(f); err != nil {
return nil, err
}
debug := "stream start >"
if f.StartTLS != nil {
debug += " tls"
}
debug += " mechanism("
for _, m := range f.Mechanisms.Mechanism {
debug += m
}
debug += ")"
if f.Bind != nil {
debug += " bind"
}
client.Logging.Info(debug)
return f, nil
}
func (client *Client) connect(password string) error {
if _, err := client.startStream(); err != nil {
return err
}
if err := client.Send(&messages.TLSStartTLS{}); err != nil {
return err
}
var p messages.TLSProceed
if err := client.ReadDecode(&p); err != nil {
return err
}
// Change tcp to tls
tlsconn := tls.Client(client.conn, &tls.Config{
ServerName: client.JID.Domain,
})
client.setConnection(tlsconn)
if err := tlsconn.Handshake(); err != nil {
return err
}
if err := tlsconn.VerifyHostname(client.JID.Domain); err != nil {
return err
}
if err := client.auth(password); err != nil {
return err
}
if _, err := client.startStream(); err != nil {
return err
}
// bind to resource
bind := &messages.Bind{}
if client.JID.Resource != "" {
bind.Resource = client.JID.Resource
}
if err := client.Send(&messages.IQClient{
Type: messages.IQTypeSet,
To: model.NewJID(client.JID.Domain),
Bind: bind,
}); err != nil {
return err
}
var iq messages.IQClient
if err := client.ReadDecode(&iq); err != nil {
return err
}
if iq.Error != nil {
if iq.Error.ServiceUnavailable == nil {
return errors.New(fmt.Sprintf("recv error on iq>bind: %s[%s]: %s -> %s -> %s", iq.Error.Code, iq.Error.Type, iq.Error.Text, messages.XMLChildrenString(iq.Error.StanzaErrorGroup), messages.XMLChildrenString(iq.Error.Other)))
} else {
client.Logging.Warn("connected without setting resource with bind after auth: service-unavailable")
}
} else if iq.Bind == nil {
return errors.New("<iq> result missing <bind>")
} else if iq.Bind.JID != nil {
client.JID.Local = iq.Bind.JID.Local
client.JID.Domain = iq.Bind.JID.Domain
client.JID.Resource = iq.Bind.JID.Resource
client.Logging.Info("set resource by server bind")
} else {
return errors.New(messages.XMLChildrenString(iq.Other))
}
// set status
return client.Send(&messages.PresenceClient{Show: messages.PresenceShowXA, Status: "online"})
}

View File

@ -38,8 +38,18 @@ var TesterCMD = &cobra.Command{
if err := file.ReadJSON(configTester.AccountsPath, testerInstance); err != nil { if err := file.ReadJSON(configTester.AccountsPath, testerInstance); err != nil {
log.Warn("unable to load state file:", err) log.Warn("unable to load state file:", err)
} }
testerInstance.Admins = configTester.Admins
testerInstance.LoggingBots = configTester.LoggingBots
clientLogger := log.New()
clientLogger.SetLevel(configTester.LoggingClients)
testerInstance.LoggingClients = clientLogger
mainClient, err := client.NewClientProtocolDuration(configTester.Client.JID, configTester.Client.Password, "tcp", configTester.Timeout.Duration) mainClient := &client.Client{
JID: configTester.Client.JID,
Timeout: configTester.Timeout.Duration,
Logging: clientLogger,
}
err := mainClient.Connect(configTester.Client.Password)
if err != nil { if err != nil {
log.Fatal("unable to connect with main jabber client: ", err) log.Fatal("unable to connect with main jabber client: ", err)
} }

View File

@ -9,8 +9,13 @@ import (
) )
func (t *Tester) StartBot(status *Status) { func (t *Tester) StartBot(status *Status) {
logger := log.New()
logger.SetLevel(t.LoggingBots)
logCTX := logger.WithFields(log.Fields{
"type": "bot",
"jid": status.client.JID.Full(),
})
for { for {
logCTX := log.WithField("jid", status.client.JID.Full())
element, err := status.client.Read() element, err := status.client.Read()
if err != nil { if err != nil {
@ -21,7 +26,7 @@ func (t *Tester) StartBot(status *Status) {
} }
errMSG := &messages.StreamError{} errMSG := &messages.StreamError{}
err = status.client.In.DecodeElement(errMSG, element) err = status.client.Decode(errMSG, element)
if err == nil { if err == nil {
logCTX.Errorf("recv stream error: %s: %s", errMSG.Text, messages.XMLChildrenString(errMSG.Any)) logCTX.Errorf("recv stream error: %s: %s", errMSG.Text, messages.XMLChildrenString(errMSG.Any))
status.client.Close() status.client.Close()
@ -30,14 +35,14 @@ func (t *Tester) StartBot(status *Status) {
} }
iq := &messages.IQClient{} iq := &messages.IQClient{}
err = status.client.In.DecodeElement(iq, element) err = status.client.Decode(iq, element)
if err == nil { if err == nil {
if iq.Ping != nil { if iq.Ping != nil {
logCTX.Debug("answer ping") logCTX.Debug("answer ping")
iq.Type = messages.IQTypeResult iq.Type = messages.IQTypeResult
iq.To = iq.From iq.To = iq.From
iq.From = status.client.JID iq.From = status.client.JID
status.client.Out.Encode(iq) status.client.Send(iq)
} else { } else {
logCTX.Warnf("recv iq unsupport: %s", messages.XMLChildrenString(iq)) logCTX.Warnf("recv iq unsupport: %s", messages.XMLChildrenString(iq))
} }
@ -45,7 +50,7 @@ func (t *Tester) StartBot(status *Status) {
} }
pres := &messages.PresenceClient{} pres := &messages.PresenceClient{}
err = status.client.In.DecodeElement(pres, element) err = status.client.Decode(pres, element)
if err == nil { if err == nil {
sender := pres.From sender := pres.From
logPres := logCTX.WithField("from", sender.Full()) logPres := logCTX.WithField("from", sender.Full())
@ -54,12 +59,12 @@ func (t *Tester) StartBot(status *Status) {
pres.Type = messages.PresenceTypeSubscribed pres.Type = messages.PresenceTypeSubscribed
pres.To = sender pres.To = sender
pres.From = nil pres.From = nil
status.client.Out.Encode(pres) status.client.Send(pres)
logPres.Debugf("accept new subscribe") logPres.Debugf("accept new subscribe")
pres.Type = messages.PresenceTypeSubscribe pres.Type = messages.PresenceTypeSubscribe
pres.ID = "" pres.ID = ""
status.client.Out.Encode(pres) status.client.Send(pres)
logPres.Info("request also subscribe") logPres.Info("request also subscribe")
} else if pres.Type == messages.PresenceTypeSubscribed { } else if pres.Type == messages.PresenceTypeSubscribed {
logPres.Info("recv presence accepted subscribe") logPres.Info("recv presence accepted subscribe")
@ -76,7 +81,7 @@ func (t *Tester) StartBot(status *Status) {
} }
msg := &messages.MessageClient{} msg := &messages.MessageClient{}
err = status.client.In.DecodeElement(msg, element) err = status.client.Decode(msg, element)
if err != nil { if err != nil {
logCTX.Warnf("unsupport xml recv: %s <-> %v", err, element) logCTX.Warnf("unsupport xml recv: %s <-> %v", err, element)
continue continue
@ -100,6 +105,30 @@ func (t *Tester) StartBot(status *Status) {
case "ping": case "ping":
status.client.Send(messages.MessageClient{Type: msg.Type, To: msg.From, Body: "pong"}) status.client.Send(messages.MessageClient{Type: msg.Type, To: msg.From, Body: "pong"})
case "disconnect":
first := true
allAdmins := ""
isAdmin := false
for _, jid := range t.Admins {
if first {
first = false
} else {
allAdmins += ", "
}
allAdmins += jid.Bare()
if jid.Bare() == msg.From.Bare() {
isAdmin = true
status.client.Send(messages.MessageClient{Type: msg.Type, To: jid, Body: "last message, disconnect requested by " + msg.From.Bare()})
}
}
if isAdmin {
status.Login = false
status.client.Close()
return
}
status.client.Send(messages.MessageClient{Type: msg.Type, To: msg.From, Body: "not allowed, ask " + allAdmins})
case "checkmsg": case "checkmsg":
if len(msgText) == 2 { if len(msgText) == 2 {
t.UpdateConnectionStatus(msg.From, status.client.JID, msgText[1]) t.UpdateConnectionStatus(msg.From, status.client.JID, msgText[1])

View File

@ -7,14 +7,16 @@ import (
) )
type Config struct { type Config struct {
TLSDir string `toml:"tlsdir"` TLSDir string `toml:"tlsdir"`
AccountsPath string `toml:"accounts_path"` AccountsPath string `toml:"accounts_path"`
OutputPath string `toml:"output_path"` OutputPath string `toml:"output_path"`
Logging log.Level `toml:"logging"` Logging log.Level `toml:"logging"`
Timeout duration.Duration `toml:"timeout"` LoggingClients log.Level `toml:"logging_clients"`
Interval duration.Duration `toml:"interval"` LoggingBots log.Level `toml:"logging_bots"`
Admins []*model.JID `toml:"admins"` Timeout duration.Duration `toml:"timeout"`
Client struct { Interval duration.Duration `toml:"interval"`
Admins []*model.JID `toml:"admins"`
Client struct {
JID *model.JID `toml:"jid"` JID *model.JID `toml:"jid"`
Password string `toml:"password"` Password string `toml:"password"`
} `toml:"client"` } `toml:"client"`

View File

@ -38,16 +38,26 @@ func (s *Status) Update(timeout time.Duration) {
return return
} }
bareJID := model.NewJID(s.account.JID.Bare()) c := &client.Client{
if client, err := client.NewClientProtocolDuration(bareJID, s.account.Password, "tcp4", timeout/2); err == nil { JID: model.NewJID(s.account.JID.Bare()),
Protocol: "tcp4",
Logging: s.client.Logging,
Timeout: timeout / 2,
}
if err := c.Connect(s.account.Password); err == nil {
s.IPv4 = true s.IPv4 = true
client.Close() c.Close()
} else { } else {
s.IPv4 = false s.IPv4 = false
} }
if client, err := client.NewClientProtocolDuration(bareJID, s.account.Password, "tcp6", timeout/2); err == nil {
c.JID = model.NewJID(s.account.JID.Bare())
c.Protocol = "tcp6"
if err := c.Connect(s.account.Password); err == nil {
s.IPv6 = true s.IPv6 = true
client.Close() c.Close()
} else { } else {
s.IPv6 = false s.IPv6 = false
} }

View File

@ -12,11 +12,14 @@ import (
) )
type Tester struct { type Tester struct {
mainClient *client.Client mainClient *client.Client
Timeout time.Duration `json:"-"` Timeout time.Duration `json:"-"`
Accounts map[string]*Account `json:"accounts"` Accounts map[string]*Account `json:"accounts"`
Status map[string]*Status `json:"-"` Status map[string]*Status `json:"-"`
mux sync.Mutex mux sync.Mutex
LoggingClients *log.Logger `json:"-"`
LoggingBots log.Level `json:"-"`
Admins []*model.JID `json:"-"`
} }
func NewTester() *Tester { func NewTester() *Tester {
@ -68,7 +71,12 @@ func (t *Tester) Connect(acc *Account) {
logCTX.Warn("is already loggedin") logCTX.Warn("is already loggedin")
return return
} }
c, err := client.NewClientProtocolDuration(acc.JID, acc.Password, "tcp", t.Timeout) c := &client.Client{
Timeout: t.Timeout,
JID: acc.JID,
Logging: t.LoggingClients,
}
err := c.Connect(acc.Password)
if err != nil { if err != nil {
logCTX.Warnf("could not connect client: %s", err) logCTX.Warnf("could not connect client: %s", err)
} else { } else {
@ -143,7 +151,7 @@ func (t *Tester) CheckStatus() {
logCTXTo = logCTXTo.WithField("msg-old", msg) logCTXTo = logCTXTo.WithField("msg-old", msg)
own.Connections[jid] = false own.Connections[jid] = false
if ok, exists := own.Connections[jid]; !exists || ok { if ok, exists := own.Connections[jid]; !exists || ok {
logCTXTo.Warn("could not recv msg") logCTXTo.Info("could not recv msg")
} else { } else {
logCTXTo.Debug("could not recv msg") logCTXTo.Debug("could not recv msg")
} }
@ -157,7 +165,7 @@ func (t *Tester) CheckStatus() {
To: s.JID, To: s.JID,
}) })
own.MessageForConnection[s.JID.Bare()] = msg own.MessageForConnection[s.JID.Bare()] = msg
logCTXTo.Info("test send") logCTXTo.Debug("test send")
send++ send++
} }
} }

View File

@ -11,7 +11,7 @@ type StreamFeatures struct {
XMLName xml.Name `xml:"http://etherx.jabber.org/streams features"` XMLName xml.Name `xml:"http://etherx.jabber.org/streams features"`
StartTLS *TLSStartTLS StartTLS *TLSStartTLS
Mechanisms SASLMechanisms Mechanisms SASLMechanisms
Bind Bind Bind *Bind
Session bool Session bool
} }

View File

@ -17,6 +17,18 @@ type XMLElement struct {
InnerXML string `xml:",innerxml"` InnerXML string `xml:",innerxml"`
} }
func XMLStartElementToString(element *xml.StartElement) string {
if element == nil {
return "<nil>"
}
debug := fmt.Sprintf("<%s xmlns=\"%s\"", element.Name.Local, element.Name.Space)
for _, attr := range element.Attr {
debug = fmt.Sprintf("%s %s=\"%s\"", debug, attr.Name, attr.Value)
}
debug += ">"
return debug
}
func XMLChildrenString(o interface{}) (result string) { func XMLChildrenString(o interface{}) (result string) {
first := true first := true
val := reflect.ValueOf(o) val := reflect.ValueOf(o)