write some dirty extension (to be compatible with gajim
This commit is contained in:
parent
1aceea7133
commit
5d8c92a76a
|
@ -30,7 +30,7 @@ var (
|
|||
statesaveWorker *worker.Worker
|
||||
srv *server.Server
|
||||
certs *tls.Config
|
||||
extensions []extension.Extension
|
||||
extensions extension.Extensions
|
||||
)
|
||||
|
||||
// serverCmd represents the serve command
|
||||
|
@ -178,8 +178,19 @@ func reload() {
|
|||
}
|
||||
|
||||
func init() {
|
||||
extensions = append(extensions,
|
||||
&extension.Message{},
|
||||
extension.IQExtensions{
|
||||
&extension.Private{},
|
||||
&extension.Ping{},
|
||||
&extension.Disco{Database: db},
|
||||
&extension.Roster{Database: db},
|
||||
&extension.ExtensionDiscovery{GetSpaces: func() []string {
|
||||
return extensions.Spaces()
|
||||
}},
|
||||
})
|
||||
|
||||
RootCmd.AddCommand(serverCmd)
|
||||
serverCmd.Flags().StringVarP(&configPath, "config", "c", "yaja.conf", "Path to configuration file")
|
||||
|
||||
extensions = append(extensions, &extension.Message{}, &extension.Roster{Database: db})
|
||||
}
|
||||
|
|
|
@ -66,3 +66,18 @@ func (s *State) Authenticate(jid *model.JID, password string) (bool, error) {
|
|||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (s *State) GetAccount(jid *model.JID) *model.Account {
|
||||
logger := log.WithField("database", "get")
|
||||
|
||||
if domain, ok := s.Domains[jid.Domain]; ok {
|
||||
if acc, ok := domain.Accounts[jid.Local]; ok {
|
||||
return acc
|
||||
} else {
|
||||
logger.Debug("account not found")
|
||||
}
|
||||
} else {
|
||||
logger.Debug("domain not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,4 +16,6 @@ const (
|
|||
NSIQRegister = "jabber:iq:register"
|
||||
|
||||
NSFeaturesIQRegister = "http://jabber.org/features/iq-register"
|
||||
|
||||
NSDisco = "http://jabber.org/protocol/disco#info"
|
||||
)
|
||||
|
|
|
@ -29,10 +29,11 @@ func (d *Domain) UpdateAccount(a *Account) error {
|
|||
}
|
||||
|
||||
type Account struct {
|
||||
Local string `json:"-"`
|
||||
Domain *Domain `json:"-"`
|
||||
Password string `json:"password"`
|
||||
Roster map[string]*Buddy `json:"roster"`
|
||||
Local string `json:"-"`
|
||||
Domain *Domain `json:"-"`
|
||||
Password string `json:"password"`
|
||||
Roster map[string]*Buddy `json:"roster"`
|
||||
Bookmarks map[string]*Bookmark `json:"bookmarks"`
|
||||
}
|
||||
|
||||
func NewAccount(jid *JID, password string) *Account {
|
||||
|
|
|
@ -15,3 +15,6 @@ type Buddy struct {
|
|||
Subscription int `json:"subscription"`
|
||||
Ask int `json:"ask"`
|
||||
}
|
||||
|
||||
type Bookmark struct {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type IQExtensions []IQExtension
|
||||
|
||||
type IQExtension interface {
|
||||
Extension
|
||||
Get(*messages.IQ, *utils.Client) bool
|
||||
Set(*messages.IQ, *utils.Client) bool
|
||||
}
|
||||
|
||||
func (iex IQExtensions) Spaces() (result []string) {
|
||||
for _, extension := range iex {
|
||||
spaces := extension.Spaces()
|
||||
result = append(result, spaces...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (iex IQExtensions) Process(element *xml.StartElement, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "iq")
|
||||
|
||||
// iq encode
|
||||
var msg messages.IQ
|
||||
if err := client.In.DecodeElement(&msg, element); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
log = log.WithField("id", msg.ID)
|
||||
|
||||
// run every extensions
|
||||
count := 0
|
||||
for _, extension := range iex {
|
||||
switch msg.Type {
|
||||
case messages.IQTypeGet:
|
||||
if extension.Get(&msg, client) {
|
||||
count++
|
||||
}
|
||||
case messages.IQTypeSet:
|
||||
if extension.Set(&msg, client) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not extensions found
|
||||
if count != 1 {
|
||||
log.Debug(msg.XMLName.Space, " - ", msg.Type, ": ", string(msg.Body))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/database"
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type Disco struct {
|
||||
IQExtension
|
||||
Database *database.State
|
||||
}
|
||||
|
||||
func (r *Disco) Spaces() []string { return []string{} }
|
||||
|
||||
func (r *Disco) Get(msg *messages.IQ, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "disco-item").WithField("id", msg.ID)
|
||||
|
||||
// query encode
|
||||
type query struct {
|
||||
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items query"`
|
||||
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"`
|
||||
}
|
||||
if acc := r.Database.GetAccount(client.JID); acc != nil {
|
||||
for jid, _ := range acc.Bookmarks {
|
||||
itemByte, err := xml.Marshal(&item{
|
||||
JID: jid,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
continue
|
||||
}
|
||||
q.Body = append(q.Body, itemByte...)
|
||||
}
|
||||
}
|
||||
|
||||
// decode query
|
||||
queryByte, err := xml.Marshal(q)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return false
|
||||
}
|
||||
|
||||
// reply
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: queryByte,
|
||||
})
|
||||
|
||||
log.Debug("send")
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type ExtensionDiscovery struct {
|
||||
IQExtension
|
||||
GetSpaces func() []string
|
||||
}
|
||||
|
||||
func (ex *ExtensionDiscovery) Spaces() []string { return []string{} }
|
||||
|
||||
func (ex *ExtensionDiscovery) Get(msg *messages.IQ, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "roster").WithField("id", msg.ID)
|
||||
|
||||
// query encode
|
||||
type query struct {
|
||||
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"`
|
||||
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 feature struct {
|
||||
XMLName xml.Name `xml:"feature"`
|
||||
Var string `xml:"var,attr"`
|
||||
}
|
||||
for _, namespace := range ex.GetSpaces() {
|
||||
if namespace == "" {
|
||||
continue
|
||||
}
|
||||
itemByte, err := xml.Marshal(&feature{
|
||||
Var: namespace,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
continue
|
||||
}
|
||||
q.Body = append(q.Body, itemByte...)
|
||||
}
|
||||
|
||||
// decode query
|
||||
queryByte, err := xml.Marshal(q)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return false
|
||||
}
|
||||
|
||||
// replay
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: queryByte,
|
||||
})
|
||||
|
||||
log.Debug("send")
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type Ping struct {
|
||||
IQExtension
|
||||
}
|
||||
|
||||
func (p *Ping) Spaces() []string { return []string{"urn:xmpp:ping"} }
|
||||
|
||||
func (p *Ping) Get(msg *messages.IQ, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "ping").WithField("id", msg.ID)
|
||||
|
||||
// ping encode
|
||||
type ping struct {
|
||||
XMLName xml.Name `xml:"urn:xmpp:ping ping"`
|
||||
}
|
||||
pq := &ping{}
|
||||
err := xml.Unmarshal(msg.Body, pq)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// reply
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
})
|
||||
|
||||
log.Debug("send")
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type Private struct {
|
||||
IQExtension
|
||||
}
|
||||
|
||||
type privateQuery struct {
|
||||
XMLName xml.Name `xml:"jabber:iq:private query"`
|
||||
Body []byte `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type ioPrivateExtension interface {
|
||||
Handle(*messages.IQ, *privateQuery, *utils.Client) bool
|
||||
}
|
||||
|
||||
func (p *Private) Spaces() []string { return []string{"jabber:iq:private"} }
|
||||
|
||||
func (p *Private) Get(msg *messages.IQ, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "private").WithField("id", msg.ID)
|
||||
|
||||
// query encode
|
||||
q := &privateQuery{}
|
||||
err := xml.Unmarshal(msg.Body, q)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// run every extensions
|
||||
count := 0
|
||||
for _, e := range []ioPrivateExtension{
|
||||
&PrivateMetacontact{},
|
||||
&PrivateRoster{},
|
||||
} {
|
||||
if e.Handle(msg, q, client) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
// not extensions found
|
||||
if count != 1 {
|
||||
log.Debug(msg.XMLName.Space, " - ", msg.Type, ": ", string(q.Body))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type PrivateMetacontact struct {
|
||||
ioPrivateExtension
|
||||
}
|
||||
|
||||
func (p *PrivateMetacontact) Handle(msg *messages.IQ, q *privateQuery, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "private-metacontact").WithField("id", msg.ID)
|
||||
|
||||
// storage encode
|
||||
type storage struct {
|
||||
XMLName xml.Name `xml:"storage:metacontacts storage"`
|
||||
}
|
||||
s := &storage{}
|
||||
err := xml.Unmarshal(q.Body, s)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
/*
|
||||
TODO full implement XEP-0209
|
||||
https://xmpp.org/extensions/xep-0209.html
|
||||
*/
|
||||
|
||||
queryByte, err := xml.Marshal(&privateQuery{
|
||||
Body: q.Body,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return true
|
||||
}
|
||||
|
||||
// reply
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: queryByte,
|
||||
})
|
||||
|
||||
log.Debug("send")
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type PrivateRoster struct {
|
||||
ioPrivateExtension
|
||||
}
|
||||
|
||||
func (p *PrivateRoster) Handle(msg *messages.IQ, q *privateQuery, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "private").WithField("id", msg.ID)
|
||||
|
||||
// roster encode
|
||||
type roster struct {
|
||||
XMLName xml.Name `xml:"roster:delimiter roster"`
|
||||
Body []byte `xml:",innerxml"`
|
||||
}
|
||||
r := &roster{}
|
||||
err := xml.Unmarshal(q.Body, r)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
rosterByte, err := xml.Marshal(&roster{
|
||||
Body: []byte("::"),
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return true
|
||||
}
|
||||
queryByte, err := xml.Marshal(&privateQuery{
|
||||
Body: rosterByte,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return true
|
||||
}
|
||||
|
||||
// reply
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: queryByte,
|
||||
})
|
||||
|
||||
log.Debug("send")
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/database"
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type Roster struct {
|
||||
IQExtension
|
||||
Database *database.State
|
||||
}
|
||||
|
||||
func (r *Roster) Spaces() []string { return []string{"jabber:iq:roster"} }
|
||||
|
||||
func (r *Roster) Get(msg *messages.IQ, client *utils.Client) bool {
|
||||
log := client.Log.WithField("extension", "roster").WithField("id", msg.ID)
|
||||
|
||||
// query encode
|
||||
type query struct {
|
||||
XMLName xml.Name `xml:"jabber:iq:roster query"`
|
||||
Version string `xml:"ver,attr"`
|
||||
Body []byte `xml:",innerxml"`
|
||||
}
|
||||
q := &query{}
|
||||
err := xml.Unmarshal(msg.Body, q)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// answer query
|
||||
q.Body = []byte{}
|
||||
q.Version = "1"
|
||||
|
||||
// build answer body
|
||||
type item struct {
|
||||
XMLName xml.Name `xml:"item"`
|
||||
JID string `xml:"jid,attr"`
|
||||
}
|
||||
if acc := r.Database.GetAccount(client.JID); acc != nil {
|
||||
for jid, _ := range acc.Roster {
|
||||
itemByte, err := xml.Marshal(&item{
|
||||
JID: jid,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
continue
|
||||
}
|
||||
q.Body = append(q.Body, itemByte...)
|
||||
}
|
||||
}
|
||||
|
||||
// decode query
|
||||
queryByte, err := xml.Marshal(q)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
return false
|
||||
}
|
||||
|
||||
// reply
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: queryByte,
|
||||
})
|
||||
|
||||
log.Debug("send")
|
||||
|
||||
return true
|
||||
}
|
|
@ -6,6 +6,33 @@ import (
|
|||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type Extensions []Extension
|
||||
|
||||
type Extension interface {
|
||||
Process(*xml.StartElement, *utils.Client) bool
|
||||
Spaces() []string
|
||||
}
|
||||
|
||||
func (ex Extensions) Spaces() (result []string) {
|
||||
for _, extension := range ex {
|
||||
result = append(result, extension.Spaces()...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (ex Extensions) Process(element *xml.StartElement, client *utils.Client) {
|
||||
log := client.Log.WithField("extension", "all")
|
||||
|
||||
// run every extensions
|
||||
count := 0
|
||||
for _, extension := range ex {
|
||||
if extension.Process(element, client) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
// not extensions found
|
||||
if count != 1 {
|
||||
log.Debug(element)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ type Message struct {
|
|||
Extension
|
||||
}
|
||||
|
||||
func (m *Message) Spaces() []string { return []string{} }
|
||||
|
||||
func (m *Message) Process(element *xml.StartElement, client *utils.Client) bool {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
package extension
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/genofire/yaja/database"
|
||||
"github.com/genofire/yaja/messages"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
type Roster struct {
|
||||
Extension
|
||||
Database *database.State
|
||||
}
|
||||
|
||||
func (r *Roster) Process(element *xml.StartElement, client *utils.Client) bool {
|
||||
var msg messages.IQ
|
||||
if err := client.In.DecodeElement(&msg, element); err != nil {
|
||||
client.Log.Warn("is no iq: ", err)
|
||||
return false
|
||||
}
|
||||
if msg.Type != messages.IQTypeGet {
|
||||
client.Log.Warn("is no get iq")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -22,7 +22,7 @@ type Server struct {
|
|||
LoggingClient log.Level
|
||||
RegisterEnable bool
|
||||
RegisterDomains []string
|
||||
Extensions []extension.Extension
|
||||
Extensions extension.Extensions
|
||||
}
|
||||
|
||||
func (srv *Server) Start() {
|
||||
|
@ -74,7 +74,7 @@ func (srv *Server) handleServer(conn net.Conn) {
|
|||
func (srv *Server) handleClient(conn net.Conn) {
|
||||
log.Info("new client connection:", conn.RemoteAddr())
|
||||
client := utils.NewClient(conn, srv.LoggingClient)
|
||||
state := toclient.ConnectionStartup(srv.Database, srv.TLSConfig, srv.TLSManager, srv.DomainRegisterAllowed)
|
||||
state := toclient.ConnectionStartup(srv.Database, srv.TLSConfig, srv.TLSManager, srv.DomainRegisterAllowed, srv.Extensions)
|
||||
|
||||
for {
|
||||
state, client = state.Process(client)
|
||||
|
|
|
@ -16,8 +16,8 @@ import (
|
|||
)
|
||||
|
||||
// ConnectionStartup return steps through TCP TLS state
|
||||
func ConnectionStartup(db *database.State, tlsconfig *tls.Config, tlsmgmt *autocert.Manager, registerAllowed utils.DomainRegisterAllowed) state.State {
|
||||
receiving := &ReceivingClient{}
|
||||
func ConnectionStartup(db *database.State, tlsconfig *tls.Config, tlsmgmt *autocert.Manager, registerAllowed utils.DomainRegisterAllowed, extensions []extension.Extension) state.State {
|
||||
receiving := &ReceivingClient{Extensions: extensions}
|
||||
sending := &SendingClient{Next: receiving}
|
||||
authedstream := &AuthedStream{Next: sending}
|
||||
authedstart := &AuthedStart{Next: authedstream}
|
||||
|
@ -213,6 +213,8 @@ func (state *AuthedStream) Process(client *utils.Client) (state.State, *utils.Cl
|
|||
client.Log = client.Log.WithField("jid", client.JID.Full())
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: []byte(fmt.Sprintf(
|
||||
`<bind xmlns='%s'>
|
||||
|
@ -223,50 +225,3 @@ func (state *AuthedStream) Process(client *utils.Client) (state.State, *utils.Cl
|
|||
|
||||
return state.Next, client
|
||||
}
|
||||
|
||||
// SendingClient state
|
||||
type SendingClient struct {
|
||||
Next state.State
|
||||
}
|
||||
|
||||
// Process messages
|
||||
func (state *SendingClient) Process(client *utils.Client) (state.State, *utils.Client) {
|
||||
client.Log = client.Log.WithField("state", "normal")
|
||||
client.Log.Debug("sending")
|
||||
// sending
|
||||
go func() {
|
||||
select {
|
||||
case msg := <-client.Messages:
|
||||
err := client.Out.Encode(msg)
|
||||
client.Log.Info(err)
|
||||
case <-client.OnClose():
|
||||
return
|
||||
}
|
||||
}()
|
||||
client.Log.Debug("receiving")
|
||||
return state.Next, client
|
||||
}
|
||||
|
||||
// ReceivingClient state
|
||||
type ReceivingClient struct {
|
||||
Extensions []extension.Extension
|
||||
}
|
||||
|
||||
// Process messages
|
||||
func (state *ReceivingClient) Process(client *utils.Client) (state.State, *utils.Client) {
|
||||
element, err := client.Read()
|
||||
if err != nil {
|
||||
client.Log.Warn("unable to read: ", err)
|
||||
return nil, client
|
||||
}
|
||||
count := 0
|
||||
for _, extension := range state.Extensions {
|
||||
if extension.Process(element, client) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count != 1 {
|
||||
client.Log.WithField("extension", count).Debug(element)
|
||||
}
|
||||
return state, client
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package toclient
|
||||
|
||||
import (
|
||||
"github.com/genofire/yaja/server/extension"
|
||||
"github.com/genofire/yaja/server/state"
|
||||
"github.com/genofire/yaja/server/utils"
|
||||
)
|
||||
|
||||
// SendingClient state
|
||||
type SendingClient struct {
|
||||
Next state.State
|
||||
}
|
||||
|
||||
// Process messages
|
||||
func (state *SendingClient) Process(client *utils.Client) (state.State, *utils.Client) {
|
||||
client.Log = client.Log.WithField("state", "normal")
|
||||
client.Log.Debug("sending")
|
||||
// sending
|
||||
go func() {
|
||||
select {
|
||||
case msg := <-client.Messages:
|
||||
err := client.Out.Encode(msg)
|
||||
client.Log.Info(err)
|
||||
case <-client.OnClose():
|
||||
return
|
||||
}
|
||||
}()
|
||||
client.Log.Debug("receiving")
|
||||
return state.Next, client
|
||||
}
|
||||
|
||||
// ReceivingClient state
|
||||
type ReceivingClient struct {
|
||||
Extensions extension.Extensions
|
||||
}
|
||||
|
||||
// Process messages
|
||||
func (state *ReceivingClient) Process(client *utils.Client) (state.State, *utils.Client) {
|
||||
element, err := client.Read()
|
||||
if err != nil {
|
||||
client.Log.Warn("unable to read: ", err)
|
||||
return nil, client
|
||||
}
|
||||
state.Extensions.Process(element, client)
|
||||
return state, client
|
||||
}
|
|
@ -53,6 +53,8 @@ func (state *RegisterFormRequest) Process(client *utils.Client) (state.State, *u
|
|||
}
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: []byte(fmt.Sprintf(`<query xmlns='%s'><instructions>
|
||||
Choose a username and password for use with this service.
|
||||
|
@ -118,6 +120,8 @@ func (state *RegisterRequest) Process(client *utils.Client) (state.State, *utils
|
|||
if err != nil {
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
Body: []byte(fmt.Sprintf(`<query xmlns='%s'>
|
||||
<username>%s</username>
|
||||
|
@ -137,6 +141,8 @@ func (state *RegisterRequest) Process(client *utils.Client) (state.State, *utils
|
|||
}
|
||||
client.Out.Encode(&messages.IQ{
|
||||
Type: messages.IQTypeResult,
|
||||
To: client.JID.String(),
|
||||
From: client.JID.Domain,
|
||||
ID: msg.ID,
|
||||
})
|
||||
|
||||
|
|
Reference in New Issue