From 1e2e57807684bb8db0cf56ad1733a6ad177d246d Mon Sep 17 00:00:00 2001 From: Martin Geno Date: Sun, 17 Dec 2017 15:39:36 +0100 Subject: [PATCH] write dirty presence extensions --- cmd/server.go | 12 +++-- config_example.conf | 2 +- server/extension/iq_disco.go | 12 ++--- server/extension/iq_discovery.go | 10 ++-- server/extension/iq_last.go | 60 +++++++++++++++++++++ server/extension/iq_ping.go | 10 ++-- server/extension/iq_private.go | 21 ++++---- server/extension/iq_private_bookmarks.go | 50 +++++++++++++++++ server/extension/iq_private_metacontacts.go | 12 ++--- server/extension/iq_private_roster.go | 12 ++--- server/extension/iq_roster.go | 12 ++--- server/extension/message.go | 2 + server/extension/presence.go | 32 +++++++++++ server/toclient/normal.go | 4 +- server/utils/client.go | 11 ++-- 15 files changed, 206 insertions(+), 56 deletions(-) create mode 100644 server/extension/iq_last.go create mode 100644 server/extension/iq_private_bookmarks.go create mode 100644 server/extension/presence.go diff --git a/cmd/server.go b/cmd/server.go index fcf59c2..43dccb0 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -180,12 +180,14 @@ func reload() { func init() { extensions = append(extensions, &extension.Message{}, + &extension.Presence{}, extension.IQExtensions{ - &extension.Private{}, - &extension.Ping{}, - &extension.Disco{Database: db}, - &extension.Roster{Database: db}, - &extension.ExtensionDiscovery{GetSpaces: func() []string { + &extension.IQPrivate{}, + &extension.IQPing{}, + &extension.IQLast{}, + &extension.IQDisco{Database: db}, + &extension.IQRoster{Database: db}, + &extension.IQExtensionDiscovery{GetSpaces: func() []string { return extensions.Spaces() }}, }) diff --git a/config_example.conf b/config_example.conf index 6051ff6..7ea1df2 100644 --- a/config_example.conf +++ b/config_example.conf @@ -2,7 +2,7 @@ tlsdir = "tmp/ssl" state_path = "tmp/yaja.json" [logging] -level = 6 +level = 3 level_client = 6 [register] diff --git a/server/extension/iq_disco.go b/server/extension/iq_disco.go index 21791fa..1c65d41 100644 --- a/server/extension/iq_disco.go +++ b/server/extension/iq_disco.go @@ -8,14 +8,14 @@ import ( "github.com/genofire/yaja/server/utils" ) -type Disco struct { +type IQDisco struct { IQExtension Database *database.State } -func (r *Disco) Spaces() []string { return []string{} } +func (ex *IQDisco) Spaces() []string { return []string{"http://jabber.org/protocol/disco#items"} } -func (r *Disco) Get(msg *messages.IQ, client *utils.Client) bool { +func (ex *IQDisco) Get(msg *messages.IQ, client *utils.Client) bool { log := client.Log.WithField("extension", "disco-item").WithField("id", msg.ID) // query encode @@ -37,7 +37,7 @@ func (r *Disco) Get(msg *messages.IQ, client *utils.Client) bool { XMLName xml.Name `xml:"item"` JID string `xml:"jid,attr"` } - if acc := r.Database.GetAccount(client.JID); acc != nil { + if acc := ex.Database.GetAccount(client.JID); acc != nil { for jid, _ := range acc.Bookmarks { itemByte, err := xml.Marshal(&item{ JID: jid, @@ -58,13 +58,13 @@ func (r *Disco) Get(msg *messages.IQ, client *utils.Client) bool { } // reply - client.Out.Encode(&messages.IQ{ + client.Messages <- &messages.IQ{ Type: messages.IQTypeResult, To: client.JID.String(), From: client.JID.Domain, ID: msg.ID, Body: queryByte, - }) + } log.Debug("send") diff --git a/server/extension/iq_discovery.go b/server/extension/iq_discovery.go index d79f497..1ad4a77 100644 --- a/server/extension/iq_discovery.go +++ b/server/extension/iq_discovery.go @@ -7,14 +7,14 @@ import ( "github.com/genofire/yaja/server/utils" ) -type ExtensionDiscovery struct { +type IQExtensionDiscovery struct { IQExtension GetSpaces func() []string } -func (ex *ExtensionDiscovery) Spaces() []string { return []string{} } +func (ex *IQExtensionDiscovery) Spaces() []string { return []string{} } -func (ex *ExtensionDiscovery) Get(msg *messages.IQ, client *utils.Client) bool { +func (ex *IQExtensionDiscovery) Get(msg *messages.IQ, client *utils.Client) bool { log := client.Log.WithField("extension", "roster").WithField("id", msg.ID) // query encode @@ -58,13 +58,13 @@ func (ex *ExtensionDiscovery) Get(msg *messages.IQ, client *utils.Client) bool { } // replay - client.Out.Encode(&messages.IQ{ + client.Messages <- &messages.IQ{ Type: messages.IQTypeResult, To: client.JID.String(), From: client.JID.Domain, ID: msg.ID, Body: queryByte, - }) + } log.Debug("send") diff --git a/server/extension/iq_last.go b/server/extension/iq_last.go new file mode 100644 index 0000000..6e575ef --- /dev/null +++ b/server/extension/iq_last.go @@ -0,0 +1,60 @@ +package extension + +import ( + "encoding/xml" + + "github.com/genofire/yaja/messages" + "github.com/genofire/yaja/server/utils" +) + +//TODO Draft + +type IQLast struct { + IQExtension +} + +func (ex *IQLast) Spaces() []string { return []string{"jabber:iq:last"} } + +func (ex *IQLast) Get(msg *messages.IQ, client *utils.Client) bool { + log := client.Log.WithField("extension", "last").WithField("id", msg.ID) + + // query encode + type query struct { + XMLName xml.Name `xml:"jabber:iq:last query"` + Seconds uint `xml:"seconds,attr,omitempty"` + Body []byte `xml:",innerxml"` + } + q := &query{} + err := xml.Unmarshal(msg.Body, q) + if err != nil { + return false + } + + // answer query + q.Body = []byte{} + + // build answer body + type item struct { + XMLName xml.Name `xml:"item"` + JID string `xml:"jid,attr"` + } + // decode query + queryByte, err := xml.Marshal(q) + if err != nil { + log.Warn(err) + return false + } + + // reply + client.Messages <- &messages.IQ{ + Type: messages.IQTypeResult, + To: client.JID.String(), + From: client.JID.Domain, + ID: msg.ID, + Body: queryByte, + } + + log.Debug("send") + + return true +} diff --git a/server/extension/iq_ping.go b/server/extension/iq_ping.go index 9d3e86f..eddcf27 100644 --- a/server/extension/iq_ping.go +++ b/server/extension/iq_ping.go @@ -7,13 +7,13 @@ import ( "github.com/genofire/yaja/server/utils" ) -type Ping struct { +type IQPing struct { IQExtension } -func (p *Ping) Spaces() []string { return []string{"urn:xmpp:ping"} } +func (ex *IQPing) Spaces() []string { return []string{"urn:xmpp:ping"} } -func (p *Ping) Get(msg *messages.IQ, client *utils.Client) bool { +func (ex *IQPing) Get(msg *messages.IQ, client *utils.Client) bool { log := client.Log.WithField("extension", "ping").WithField("id", msg.ID) // ping encode @@ -27,12 +27,12 @@ func (p *Ping) Get(msg *messages.IQ, client *utils.Client) bool { } // reply - client.Out.Encode(&messages.IQ{ + client.Messages <- &messages.IQ{ Type: messages.IQTypeResult, To: client.JID.String(), From: client.JID.Domain, ID: msg.ID, - }) + } log.Debug("send") diff --git a/server/extension/iq_private.go b/server/extension/iq_private.go index 2be09f7..81d8d8d 100644 --- a/server/extension/iq_private.go +++ b/server/extension/iq_private.go @@ -7,26 +7,26 @@ import ( "github.com/genofire/yaja/server/utils" ) -type Private struct { +type IQPrivate struct { IQExtension } -type privateQuery struct { +type iqPrivateQuery struct { XMLName xml.Name `xml:"jabber:iq:private query"` Body []byte `xml:",innerxml"` } -type ioPrivateExtension interface { - Handle(*messages.IQ, *privateQuery, *utils.Client) bool +type iqPrivateExtension interface { + Handle(*messages.IQ, *iqPrivateQuery, *utils.Client) bool } -func (p *Private) Spaces() []string { return []string{"jabber:iq:private"} } +func (ex *IQPrivate) Spaces() []string { return []string{"jabber:iq:private"} } -func (p *Private) Get(msg *messages.IQ, client *utils.Client) bool { +func (ex *IQPrivate) Get(msg *messages.IQ, client *utils.Client) bool { log := client.Log.WithField("extension", "private").WithField("id", msg.ID) // query encode - q := &privateQuery{} + q := &iqPrivateQuery{} err := xml.Unmarshal(msg.Body, q) if err != nil { return false @@ -34,9 +34,10 @@ func (p *Private) Get(msg *messages.IQ, client *utils.Client) bool { // run every extensions count := 0 - for _, e := range []ioPrivateExtension{ - &PrivateMetacontact{}, - &PrivateRoster{}, + for _, e := range []iqPrivateExtension{ + &IQPrivateMetacontact{}, + &IQPrivateRoster{}, + &IQPrivateBookmark{}, } { if e.Handle(msg, q, client) { count++ diff --git a/server/extension/iq_private_bookmarks.go b/server/extension/iq_private_bookmarks.go new file mode 100644 index 0000000..a9efe4c --- /dev/null +++ b/server/extension/iq_private_bookmarks.go @@ -0,0 +1,50 @@ +package extension + +import ( + "encoding/xml" + + "github.com/genofire/yaja/messages" + "github.com/genofire/yaja/server/utils" +) + +type IQPrivateBookmark struct { + iqPrivateExtension +} + +func (ex *IQPrivateBookmark) Handle(msg *messages.IQ, q *iqPrivateQuery, client *utils.Client) bool { + log := client.Log.WithField("extension", "private").WithField("id", msg.ID) + + // storage encode + type storage struct { + XMLName xml.Name `xml:"storage:bookmarks storage"` + } + s := &storage{} + err := xml.Unmarshal(q.Body, s) + if err != nil { + return false + } + /* + TODO full implement + */ + + queryByte, err := xml.Marshal(&iqPrivateQuery{ + Body: q.Body, + }) + if err != nil { + log.Warn(err) + return true + } + + // reply + client.Messages <- &messages.IQ{ + Type: messages.IQTypeResult, + To: client.JID.String(), + From: client.JID.Domain, + ID: msg.ID, + Body: queryByte, + } + + log.Debug("send") + + return true +} diff --git a/server/extension/iq_private_metacontacts.go b/server/extension/iq_private_metacontacts.go index 9a621e2..6e897ea 100644 --- a/server/extension/iq_private_metacontacts.go +++ b/server/extension/iq_private_metacontacts.go @@ -7,11 +7,11 @@ import ( "github.com/genofire/yaja/server/utils" ) -type PrivateMetacontact struct { - ioPrivateExtension +type IQPrivateMetacontact struct { + iqPrivateExtension } -func (p *PrivateMetacontact) Handle(msg *messages.IQ, q *privateQuery, client *utils.Client) bool { +func (ex *IQPrivateMetacontact) Handle(msg *messages.IQ, q *iqPrivateQuery, client *utils.Client) bool { log := client.Log.WithField("extension", "private-metacontact").WithField("id", msg.ID) // storage encode @@ -28,7 +28,7 @@ func (p *PrivateMetacontact) Handle(msg *messages.IQ, q *privateQuery, client *u https://xmpp.org/extensions/xep-0209.html */ - queryByte, err := xml.Marshal(&privateQuery{ + queryByte, err := xml.Marshal(&iqPrivateQuery{ Body: q.Body, }) if err != nil { @@ -37,13 +37,13 @@ func (p *PrivateMetacontact) Handle(msg *messages.IQ, q *privateQuery, client *u } // reply - client.Out.Encode(&messages.IQ{ + client.Messages <- &messages.IQ{ Type: messages.IQTypeResult, To: client.JID.String(), From: client.JID.Domain, ID: msg.ID, Body: queryByte, - }) + } log.Debug("send") diff --git a/server/extension/iq_private_roster.go b/server/extension/iq_private_roster.go index 7702ebe..090dbc7 100644 --- a/server/extension/iq_private_roster.go +++ b/server/extension/iq_private_roster.go @@ -7,11 +7,11 @@ import ( "github.com/genofire/yaja/server/utils" ) -type PrivateRoster struct { - ioPrivateExtension +type IQPrivateRoster struct { + iqPrivateExtension } -func (p *PrivateRoster) Handle(msg *messages.IQ, q *privateQuery, client *utils.Client) bool { +func (ex *IQPrivateRoster) Handle(msg *messages.IQ, q *iqPrivateQuery, client *utils.Client) bool { log := client.Log.WithField("extension", "private").WithField("id", msg.ID) // roster encode @@ -32,7 +32,7 @@ func (p *PrivateRoster) Handle(msg *messages.IQ, q *privateQuery, client *utils. log.Warn(err) return true } - queryByte, err := xml.Marshal(&privateQuery{ + queryByte, err := xml.Marshal(&iqPrivateQuery{ Body: rosterByte, }) if err != nil { @@ -41,13 +41,13 @@ func (p *PrivateRoster) Handle(msg *messages.IQ, q *privateQuery, client *utils. } // reply - client.Out.Encode(&messages.IQ{ + client.Messages <- &messages.IQ{ Type: messages.IQTypeResult, To: client.JID.String(), From: client.JID.Domain, ID: msg.ID, Body: queryByte, - }) + } log.Debug("send") diff --git a/server/extension/iq_roster.go b/server/extension/iq_roster.go index 03deb6a..018d109 100644 --- a/server/extension/iq_roster.go +++ b/server/extension/iq_roster.go @@ -8,14 +8,14 @@ import ( "github.com/genofire/yaja/server/utils" ) -type Roster struct { +type IQRoster struct { IQExtension Database *database.State } -func (r *Roster) Spaces() []string { return []string{"jabber:iq:roster"} } +func (ex *IQRoster) Spaces() []string { return []string{"jabber:iq:roster"} } -func (r *Roster) Get(msg *messages.IQ, client *utils.Client) bool { +func (ex *IQRoster) Get(msg *messages.IQ, client *utils.Client) bool { log := client.Log.WithField("extension", "roster").WithField("id", msg.ID) // query encode @@ -39,7 +39,7 @@ func (r *Roster) Get(msg *messages.IQ, client *utils.Client) bool { XMLName xml.Name `xml:"item"` JID string `xml:"jid,attr"` } - if acc := r.Database.GetAccount(client.JID); acc != nil { + if acc := ex.Database.GetAccount(client.JID); acc != nil { for jid, _ := range acc.Roster { itemByte, err := xml.Marshal(&item{ JID: jid, @@ -60,13 +60,13 @@ func (r *Roster) Get(msg *messages.IQ, client *utils.Client) bool { } // reply - client.Out.Encode(&messages.IQ{ + client.Messages <- &messages.IQ{ Type: messages.IQTypeResult, To: client.JID.String(), From: client.JID.Domain, ID: msg.ID, Body: queryByte, - }) + } log.Debug("send") diff --git a/server/extension/message.go b/server/extension/message.go index 4e35e79..3daa310 100644 --- a/server/extension/message.go +++ b/server/extension/message.go @@ -10,6 +10,8 @@ type Message struct { Extension } +//TODO Draft + func (m *Message) Spaces() []string { return []string{} } func (m *Message) Process(element *xml.StartElement, client *utils.Client) bool { diff --git a/server/extension/presence.go b/server/extension/presence.go new file mode 100644 index 0000000..3a2303e --- /dev/null +++ b/server/extension/presence.go @@ -0,0 +1,32 @@ +package extension + +import ( + "encoding/xml" + + "github.com/genofire/yaja/messages" + "github.com/genofire/yaja/server/utils" +) + +type Presence struct { + Extension +} + +//TODO Draft + +func (p *Presence) Spaces() []string { return []string{} } + +func (p *Presence) Process(element *xml.StartElement, client *utils.Client) bool { + log := client.Log.WithField("extension", "presence") + + // iq encode + var msg messages.Presence + if err := client.In.DecodeElement(&msg, element); err != nil { + return false + } + client.Messages <- &messages.Presence{ + ID: msg.ID, + } + log.Debug("send") + + return true +} diff --git a/server/toclient/normal.go b/server/toclient/normal.go index d971657..b066781 100644 --- a/server/toclient/normal.go +++ b/server/toclient/normal.go @@ -20,7 +20,9 @@ func (state *SendingClient) Process(client *utils.Client) (state.State, *utils.C select { case msg := <-client.Messages: err := client.Out.Encode(msg) - client.Log.Info(err) + if err != nil { + client.Log.Warn(err) + } case <-client.OnClose(): return } diff --git a/server/utils/client.go b/server/utils/client.go index d175309..1240cc5 100644 --- a/server/utils/client.go +++ b/server/utils/client.go @@ -26,11 +26,12 @@ func NewClient(conn net.Conn, level log.Level) *Client { logger := log.New() logger.SetLevel(level) client := &Client{ - Conn: conn, - Log: log.NewEntry(logger), - In: xml.NewDecoder(conn), - Out: xml.NewEncoder(conn), - close: make(chan interface{}), + Conn: conn, + Log: log.NewEntry(logger), + In: xml.NewDecoder(conn), + Out: xml.NewEncoder(conn), + Messages: make(chan interface{}, 1000), + close: make(chan interface{}), } return client }